Re: A few simple C++ questions

Masaharu Goto (gotom@hpyiddq.jpn.hp.com)
Mon, 22 Dec 1997 9:26:44 JST


Bill,

> I have two (basic) C++ questions I would like to present to any Guru in ROOT
> land.
>
> (1): How might I pass a public member function of class MYCLASS into the
> constructor TF2?
>
> class MYCLASS
> {
> Double_t MYCLASS::myfunction(Double_t *x, Double_t *y) { return
> x[0]*X[1]; };
> };
>
> MYCLASS myclass;
> TF2 *tf2 = new TF2("name", ???myclass.myfunction???, 0, 1, 0, 1); // this
> doesn't work of course. Is there a way?

It goes as follows.

class MYCLASS {
public:
static Double_t myfunction(Double_t *x,Double_t *y) {
return x[0]*x[1];
}
};

i) Scope specification to member function definition is only necessary
when it is defined outside of class declaration. In this case, you
define myfunction within class declaration. Another way of doing the
same thing is shown below. Below case defines myfunction outside of
class declaration, then you need MYCLASS:: scope specification.

class MYCLASS {
public:
static Double_t myfunction(Double_t *x,Double_t *y) ;
};
Double_t MYCLASS::myfunction(Double_t *x,Double_t *y) {
return x[0]*x[1];
}

ii) If you want to specify the function the same way as you do for global
function, you must declare it as 'static'. Static member function is
equivalent to global function. But ordinary member function has extra
information which makes it incompatible with the global function.
In this case, you are not using data member at all. So declaring
myfunction as static is completely reasonable.

> (2): Is there a method in C++ to obtain member function resolution by return
> type? For example
>
> Double_t VECTOR::operator*(const VECTOR& rhs); // inner product
> VECTOR operator*(const VECTOR& rhs); // cross product
> MATRIX operator*(const VECTOR& rhs); // outer product
>
> Double_t result;
> VECTOR v1, v2;
> result = v2*v2; // this should use correct function based on return
> assignment.

No, this is impossible. I recommend to use different operator or
some explicit way of distinguishing inner/cross/outer products.

I can think of an ugly trick to make your code work. But it is much more
complicated than you would expect. Following code shows the concept.

class VECTOR;
class MATRIX;

class XPRODUCT { // a dummy product class which postpones actual
VECTOR *v1,*v2; // decision of inner/cross/outer product selection
public: // and calculation until point of assignment.
friend class VECTOR;
friend class MATRIX;
operator Double_t() { // assignment to Double_t
return(innerproduct(*v1,*v2)); // use inner product
}
XPRODUCT(VECTOR* v1in,VECTOR* v2in) : v1(v1in), v2(v2in) {}
};

class VECTOR {
// something here
public:
XPRODUCT operator*(VECTOR& v1,VECTOR& v2) {
XPRODUCT xprod(&v1,&v2); // create dummy product obj to postpone
return xprod; // inner/outer/cross prod decision
}
VECTOR& operator=(XPRODUCT& x) { // assignment to vector
*this = crossproduct(*x.v1 , *x.v2); // use cross product
return(*this);
}
Double_t innerproduct(VECTOR& v1,VECTOR& v2); // I do not show here
VECTOR crossproduct(VECTOR& v1,VECTOR& v2); // I do not show here
MATRIX outerproduct(VECTOR& v1,VECTOR& v2); // I do not show here
};

class MATRIX {
// something here
public:
MATRIX& operator=(XPRODUCT& x) { // assignment to matrix,
*this = outerproduct(*x.v1 , *x.v2); // use outer product
return(*this);
}
};

Novice C++ programmer may want to stay away from this. Above method only
works with only one operator per assignment, such as 'result=x*y'. You
can not use combination of operators in one statement, like 'result=x*y*z'.
If you want this also, you need to add another level of complication.

Masaharu Goto