| Home | Forums | Reviews | Guides | Newsgroups | Register | Search |
![]() |
| Thread Tools |
|
Leslaw Bieniasz
Guest
Posts: n/a
|
Cracow, 20.09.2004 Hello, I need to implement a library containing a hierarchy of classes together with some binary operations on objects. To fix attention, let me assume that it is a hierarchy of algebraic matrices with the addition operation. Thus, I want to have a virtual base class class Matr; and some derived classes: class Matr1 : public Matr; class Matr2 : public Matr; class Matr3 : public Matr2; etc. I want to be able to write the code like the following one, which intensively uses polymorphism: Matr* A = new Matr1(); Matr* B = new Matr2(); Matr* C = new Matr3(); .. .. .. Add(A, B, C); [or C->Add(A,B); ] where the addition is supposed to be implemented either as a global function that adds A to B and places the result into C, or as a virtual method of a base class, which calculates the sum of A and B, and puts the result into the object which calls the method. In the first case the function(s) would have to be friends of the Matr1, Matr2, etc. class(es). The same could be done using overloaded operators +, but this is a secondary issue for my question, see below. I also abstract, at the moment, from how exactly the binary operation is realised (for example, one might use, or not use, expression templates). The problem with the above is that each of the matrices Matr1, Matr2, Matr3,... may require a different implementation of the addition operation. For example, adding a diagonal matrix to a dense matrix is possible, but is done differently from adding a dense matrix to a dense matrix, or diagonal matrix to a diagonal matrix. Thus, I may need to have a number of versions of Add(): Add(Matr1 *A, Matr1 *B, Matr1 *C); Add(Matr2 *A, Matr2 *B, Matr2 *C); Add(Matr3 *A, Matr3 *B, Matr3 *C); but also Add(Matr1 *A, Matr2 *B, Matr3 *C); Add(Matr1 *A, Matr1 *B, Matr2 *C); and a number of other combinations. This partially satisfies the design goal, but one has to be very careful about casting the pointers prior to calling Add(), in order to ensure that a suitable variant will be called. Instead of writing Add(A, B, C); I would then have to write Add( dynamic_cast<Matr1 *>(A), dynamic_cast<Matr2 *>(B), dynamic_cast<Matr3 *>(C) ); which is obviously inconvenient, and also invalidates the idea of polymorphism, as the run type of the objects must be known at compile time. In addition any extension of the library becomes difficult, because if I define a new matrix type, together with new Add() variants needed for it, the new Add() functions will not be known as friends of the respective classes in the library. Implementing Add() as a class method would also be difficult, because there would have to be many overloaded variants in every class, the number increasing with every new derived class. A possible alternative might be to define one global function void Add(Matr *A, Matr *B, Matr *C); (or class method), and perform the run-time type checking within this function. This would require having several if-else options within the function. However this solution appears not very elegant, again somewhat inconsistent with the idea of the polymorphism, and similarly hard to extend on new matrix types (apart from being likely inefficient). In view of the above, my question is: What else can be done, using C++ capabilities, to allow me just to write Add(A, B, C); and at the same time be able to extend the library without having to make changes in the library? Sincerely, L.B. *-------------------------------------------------------------------* | Dr. Leslaw Bieniasz, | | Institute of Physical Chemistry of the Polish Academy of Sciences,| | Department of Electrochemical Oxidation of Gaseous Fuels, | | ul. Zagrody 13, 30-318 Cracow, Poland. | | tel./fax: +48 (12) 266-03-41 | | E-mail: | *-------------------------------------------------------------------* | Interested in Computational Electrochemistry? | | Visit my web site: http://www.cyf-kr.edu.pl/~nbbienia | *-------------------------------------------------------------------* |
|
|
|
|
|||
|
|||
| Leslaw Bieniasz |
|
|
|
| |
|
Paul
Guest
Posts: n/a
|
Leslaw Bieniasz <> wrote in message news:<>...
> Cracow, 20.09.2004 > > Hello, > > I need to implement a library containing a hierarchy of classes > together with some binary operations on objects. To fix attention, > let me assume that it is a hierarchy of algebraic matrices with the > addition operation. Thus, I want to have a virtual base class > > class Matr; > > and some derived classes: > > class Matr1 : public Matr; > class Matr2 : public Matr; > class Matr3 : public Matr2; > > etc. > > I want to be able to write the code like the following one, which > intensively uses polymorphism: > > Matr* A = new Matr1(); > Matr* B = new Matr2(); > Matr* C = new Matr3(); > . > . > . > Add(A, B, C); > > [or C->Add(A,B); ] > > where the addition is supposed to be implemented either as a global function > that adds A to B and places the result into C, or as a virtual method > of a base class, which calculates the sum of A and B, and puts the result > into the object which calls the method. > In the first case the function(s) would have to be friends of the Matr1, > Matr2, etc. class(es). The same could be done using overloaded operators +, > but this is a secondary issue for my question, see below. I also abstract, > at the moment, from how exactly the binary operation is realised (for > example, one might use, or not use, expression templates). You should consider a static method as an alternative to the global method: Matr::Add(A,B,C); I prefer this as it makes things clearer. Then you could experiment with different implementations of a static method in different derived classes: Matr1::Add(...); Matr2::Add(...); > > The problem with the above is that each of the matrices > Matr1, Matr2, Matr3,... may require a different implementation > of the addition operation. For example, adding a diagonal matrix to a > dense matrix is possible, but is done differently from adding a dense > matrix to a dense matrix, or diagonal matrix to a diagonal matrix. > Thus, I may need to have a number of versions of Add(): > > Add(Matr1 *A, Matr1 *B, Matr1 *C); > Add(Matr2 *A, Matr2 *B, Matr2 *C); > Add(Matr3 *A, Matr3 *B, Matr3 *C); > > but also > > Add(Matr1 *A, Matr2 *B, Matr3 *C); > Add(Matr1 *A, Matr1 *B, Matr2 *C); > > and a number of other combinations. This partially satisfies the design goal, > but one has to be very careful about casting the pointers prior to > calling Add(), in order to ensure that a suitable variant will be called. > Instead of writing > > Add(A, B, C); > > I would then have to write > > Add( dynamic_cast<Matr1 *>(A), > dynamic_cast<Matr2 *>(B), > dynamic_cast<Matr3 *>(C) ); > You don't need to do that there are better ways. One problem is that I don't know how many different parameter combinations you intend. Is it always going to be 2 or 3 parameters? With 3 parameters max and say 16 different types of matrixes the number of combinations becomes excessive for overloading. What you might want to do is make all parameters bases Add(MatrBase*, MatrBase*); now do you want to overload this to take a various numbers of arguments? Alternatively you could make it only take 2 arguments and nest function calls, then you would need to return an object: Add(Add(MatrBase*, MatrBase*), Add MatrBase*); But this could be hidden inside a class so that you only call Add on 1 object. Matr2Obj.Add( MatrBase*, MatrBase*) with an implementation of: Matr2::Add(MatrBase* arg1, MatrBase* arg2){ //done on two lines for clarity tempobj =arg1->Add(arg2); this->Add(tempObj); } so every Matrix class imlements and Add method which takes 1 parameter and does its stuff accordingly then returns an object, which will be of polymorphic type. Matr& Matr::Add(Matr*){ //do add stuff return *this; //reutrn reference or pointer or temp obj? //this depends on other aspects of your design. //reference seems like a good candidate. } I think you should consider using a return value as most add operations usually do, but you say you want to store result in a particular object so this is also a grey area without understanding more detail of your design. > which is obviously inconvenient, and also invalidates the idea > of polymorphism, as the run type of the objects must be known > at compile time. In addition any extension of the library becomes > difficult, because if I define a new matrix type, together with > new Add() variants needed for it, the new Add() functions will > not be known as friends of the respective classes in the library. I agree that type casting is not a godd way, also templates are ruled out. Extensibility should and could be preserved using the method I tried to describe above using polyorphism. > Implementing Add() as a class method would also be difficult, because > there would have to be many overloaded variants in every class, the number > increasing with every new derived class. Yes I see this, this rules out global and class methods. > > > A possible alternative might be to define one global function > > void Add(Matr *A, Matr *B, Matr *C); > > (or class method), and perform the run-time type checking within this > function. This would require having several if-else options within the > function. However this solution appears not very elegant, again somewhat > inconsistent with the idea of the polymorphism, and similarly hard to > extend on new matrix types (apart from being likely inefficient). RTTI doesn't sound like a good option. > > > In view of the above, my question is: > > What else can be done, using C++ capabilities, to allow me > just to write > > Add(A, B, C); > > and at the same time be able to extend the library > without having to make changes in the library? I'm not sure if I explained properly because I have a few grey areas about your design goals as described above, best I can see at present is to create a pure virtual Add() which takes one parameter and returns an object. Then dependant on your design goals overload this to accept more parameters with each overloaded version calling the virtual single parameter implementation of each parameter bar the last with the argument of the parameter in the parameter list. Then perhaps this can be improved upon to remove the returned object for design goal and/or efficiency reasons. > > > Sincerely, > > L.B. > > > *-------------------------------------------------------------------* > | Dr. Leslaw Bieniasz, | > | Institute of Physical Chemistry of the Polish Academy of Sciences,| > | Department of Electrochemical Oxidation of Gaseous Fuels, | > | ul. Zagrody 13, 30-318 Cracow, Poland. | > | tel./fax: +48 (12) 266-03-41 | > | E-mail: | > *-------------------------------------------------------------------* > | Interested in Computational Electrochemistry? | > | Visit my web site: http://www.cyf-kr.edu.pl/~nbbienia | > *-------------------------------------------------------------------* To sum up my patchy explanations will something like this help: class Matr{ virtual Matr& Add(Matr&)=0{return *this} }; class Matr1:Matr{ virtual Matr& Add(Matr*); virtual Matr& Add(Matr*, Matr*); virtual Matr& Add(Matr*, Matr*, Matr*); }; Matr& Matr1::Add(Matr* arg){ //do add stuff return *this; } Matr& Matr1::Add(Matr* arg1, Matr* arg2){ this->Add(arg1->Add(arg2)); return *this; } Matr& Matr1::Add(Matr* arg1, Matr* arg2, Matr* arg3){ this->Add(arg1->Add(arg2->Add(arg3))); } usage: Matr* mp_array[5] = {new Matr1, new Matr1, new Matr1, new Matr1,new Matr1}; mp_array[0]->Add(mp_array[1],mp_array[2],mp_array[3]); etc etc. HTH Paul. |
|
|
|
|
|||
|
|||
| Paul |
|
|
|
| |
| Paul |
|
Leslaw Bieniasz
Guest
Posts: n/a
|
Cracow, 22.09.2004 Hello, On Mon, 20 Sep 2004, Paul wrote: > Leslaw Bieniasz <> wrote in message news:<>... > > I need to implement a library containing a hierarchy of classes > > together with some binary operations on objects. To fix attention, > > let me assume that it is a hierarchy of algebraic matrices with the > > addition operation. Thus, I want to have a virtual base class > > > > class Matr; > > > > and some derived classes: > > > > class Matr1 : public Matr; > > class Matr2 : public Matr; > > class Matr3 : public Matr2; > > > > etc. > > > > I want to be able to write the code like the following one, which > > intensively uses polymorphism: > > > > Matr* A = new Matr1(); > > Matr* B = new Matr2(); > > Matr* C = new Matr3(); > > . > > . > > . > > Add(A, B, C); > > > > [or C->Add(A,B); ] > > > > where the addition is supposed to be implemented either as a global function > > that adds A to B and places the result into C, or as a virtual method > > of a base class, which calculates the sum of A and B, and puts the result > > into the object which calls the method. > > In the first case the function(s) would have to be friends of the Matr1, > > Matr2, etc. class(es). The same could be done using overloaded operators +, > > but this is a secondary issue for my question, see below. I also abstract, > > at the moment, from how exactly the binary operation is realised (for > > example, one might use, or not use, expression templates). > > You should consider a static method as an alternative to the global > method: > Matr::Add(A,B,C); > I prefer this as it makes things clearer. > > Then you could experiment with different implementations of a static > method in different derived classes: > Matr1::Add(...); > Matr2::Add(...); -------------------------------- I don't see how this might be helpful, as this would require the knowledge, at compile time, of which static function to call, whereas my goal is that this issue be resolved at run time. -------------------------------- > > The problem with the above is that each of the matrices > > Matr1, Matr2, Matr3,... may require a different implementation > > of the addition operation. For example, adding a diagonal matrix to a > > dense matrix is possible, but is done differently from adding a dense > > matrix to a dense matrix, or diagonal matrix to a diagonal matrix. > > Thus, I may need to have a number of versions of Add(): > > > > Add(Matr1 *A, Matr1 *B, Matr1 *C); > > Add(Matr2 *A, Matr2 *B, Matr2 *C); > > Add(Matr3 *A, Matr3 *B, Matr3 *C); > > > > but also > > > > Add(Matr1 *A, Matr2 *B, Matr3 *C); > > Add(Matr1 *A, Matr1 *B, Matr2 *C); > > > > and a number of other combinations. This partially satisfies the design goal, > > but one has to be very careful about casting the pointers prior to > > calling Add(), in order to ensure that a suitable variant will be called. > > Instead of writing > > > > Add(A, B, C); > > > > I would then have to write > > > > Add( dynamic_cast<Matr1 *>(A), > > dynamic_cast<Matr2 *>(B), > > dynamic_cast<Matr3 *>(C) ); > > > You don't need to do that there are better ways. > One problem is that I don't know how many different parameter > combinations you intend. Is it always going to be 2 or 3 parameters? > With 3 parameters max and say 16 different types of matrixes the > number of combinations becomes excessive for overloading. > What you might want to do is make all parameters bases > Add(MatrBase*, MatrBase*); > now do you want to overload this to take a various numbers of > arguments? > Alternatively you could make it only take 2 arguments and nest > function calls, then you would need to return an object: > Add(Add(MatrBase*, MatrBase*), Add MatrBase*); > But this could be hidden inside a class so that you only call Add on 1 > object. > > Matr2Obj.Add( MatrBase*, MatrBase*) > with an implementation of: > > Matr2::Add(MatrBase* arg1, MatrBase* arg2){ > //done on two lines for clarity > tempobj =arg1->Add(arg2); > this->Add(tempObj); > } > > so every Matrix class imlements and Add method which takes 1 parameter > and does its stuff accordingly then returns an object, which will be > of polymorphic type. > > Matr& Matr::Add(Matr*){ > //do add stuff > return *this; > //reutrn reference or pointer or temp obj? > //this depends on other aspects of your design. > //reference seems like a good candidate. > } > > I think you should consider using a return value as most add > operations usually do, but you say you want to store result in a > particular object so this is also a grey area without understanding > more detail of your design. ----------------------------------- No, my problem is not that I may have a variable number of addends (although this issue presents another difficulty). In the problem that I described, I always have two rvalue arguments and one lvalue argument: C = A + B but I can have multiple types of A, B, and C, so that the entire (binary) operation is polymorphic. ------------------------------------ > > which is obviously inconvenient, and also invalidates the idea > > of polymorphism, as the run type of the objects must be known > > at compile time. In addition any extension of the library becomes > > difficult, because if I define a new matrix type, together with > > new Add() variants needed for it, the new Add() functions will > > not be known as friends of the respective classes in the library. > I agree that type casting is not a godd way, also templates are ruled > out. > Extensibility should and could be preserved using the method I tried > to describe above using polyorphism. > > > Implementing Add() as a class method would also be difficult, because > > there would have to be many overloaded variants in every class, the number > > increasing with every new derived class. > > Yes I see this, this rules out global and class methods. > > > > > > A possible alternative might be to define one global function > > > > void Add(Matr *A, Matr *B, Matr *C); > > > > (or class method), and perform the run-time type checking within this > > function. This would require having several if-else options within the > > function. However this solution appears not very elegant, again somewhat > > inconsistent with the idea of the polymorphism, and similarly hard to > > extend on new matrix types (apart from being likely inefficient). > RTTI doesn't sound like a good option. > > > > > > In view of the above, my question is: > > > > What else can be done, using C++ capabilities, to allow me > > just to write > > > > Add(A, B, C); > > > > and at the same time be able to extend the library > > without having to make changes in the library? > I'm not sure if I explained properly because I have a few grey areas > about your design goals as described above, best I can see at present > is to create a pure virtual Add() which takes one parameter and > returns an object. Then dependant on your design goals overload this > to accept more parameters with each overloaded version calling the > virtual single parameter implementation of each parameter bar the last > with the argument of the parameter in the parameter list. > Then perhaps this can be improved upon to remove the returned object > for design goal and/or efficiency reasons. > > > To sum up my patchy explanations will something like this help: > > class Matr{ > virtual Matr& Add(Matr&)=0{return *this} > }; > > class Matr1:Matr{ > virtual Matr& Add(Matr*); > virtual Matr& Add(Matr*, Matr*); > virtual Matr& Add(Matr*, Matr*, Matr*); > }; > > Matr& Matr1::Add(Matr* arg){ > //do add stuff > return *this; > } > > Matr& Matr1::Add(Matr* arg1, Matr* arg2){ > this->Add(arg1->Add(arg2)); > return *this; > } > > Matr& Matr1::Add(Matr* arg1, Matr* arg2, Matr* arg3){ > this->Add(arg1->Add(arg2->Add(arg3))); > } > > usage: > Matr* mp_array[5] = {new Matr1, new Matr1, new Matr1, new Matr1,new > Matr1}; > > mp_array[0]->Add(mp_array[1],mp_array[2],mp_array[3]); > > etc etc. > ------------------------------------------- To express my problem more rigorously, I now think this is an example of the "multiple dispatch" problem, as described by Scott Meyers in "More Effective C++", Addison-wesley, 1996, p. 228. Unfortunately, he focused on the remedies for the unary operation case, such as C = A whereas I need binary (and multi-operand, as you indicated, operations). I also think that his proposal may not be very efficient, as the lookup procedure involves std::map searches, which I expect to be rather slow. Hence, I can reformulate my question: where can I find descriptions of how to handle the multiple dispatch problem efficiently and effectively in the case of binary and multi-operand operations. Sincerely, L.B. *-------------------------------------------------------------------* | Dr. Leslaw Bieniasz, | | Institute of Physical Chemistry of the Polish Academy of Sciences,| | Department of Electrochemical Oxidation of Gaseous Fuels, | | ul. Zagrody 13, 30-318 Cracow, Poland. | | tel./fax: +48 (12) 266-03-41 | | E-mail: | *-------------------------------------------------------------------* | Interested in Computational Electrochemistry? | | Visit my web site: http://www.cyf-kr.edu.pl/~nbbienia | *-------------------------------------------------------------------* |
|
|
|
|
|||
|
|||
| Leslaw Bieniasz |
|
Paul
Guest
Posts: n/a
|
Leslaw Bieniasz <> wrote in message news:<>...
> Cracow, 22.09.2004 [snip] > > ----------------------------------- > No, my problem is not that I may have a variable number of addends > (although this issue presents another difficulty). > In the problem that I described, I always have two rvalue arguments and > one lvalue argument: > > C = A + B > > but I can have multiple types of A, B, and C, so that the entire > (binary) operation is polymorphic. > ------------------------------------ It seems like will need a method for all additon combinations. for example if your library started of with 3 types of matrix say: DenseMatrix DiamondMatrix HybridMatrix Lets call them A,B and C. Then your going to need a method for each to be able to add each of the others and itself thus allowing for commutativity: A::Add(A); A::Add(B); A::Add(C); B::Add(A); B::Add(B); etc etc.. So then you can do: C=A+B; C=C+C; C=B+A; B=C+A etc etc for all combinations; Then when you later wish to add a Matrix type ,call it D, you'll need to include an Add method for each A,B and C: D::Add(A); D::Add(B); etc . So now you can do D=A+B+C; D+B; D+A But what if A,B or C tries to add D, you cannot do A=B+D because there is no method: A::Add(D) (doesn't exist) But what A can do is call D::Add(A) if A knows about D's Base class and Ds' Add method is virtual. It also has to know that it doesn't know about D, here's how you could do this: create an enumerator: enum Matrix_types{A,B,C} class A{ Matrix_types myType; int known_types; A():known_types(3),myType(A){//constructor} }; do the same for all other classes. When you want to add D you extend the enumerator to include D: enum Matrix_types{A,B,C,D} D():known_types(4), myType(D){//constructor} Now D knows of 4 types but A only knows about 3. Now back to the problem of A calling D's Add method. When A gets called to Add(D) it knows that it can only add the first 3 enumerated types(A,B and C) so what it does is call D::Add(A). D can handle A's so this is no problem. This is a design that will work but it basically requires a function for every combination of two addable Marix_types and I'm still not entirely sure this is what you want. If some of the functionality is duplicated across Methods you can reduce the size of your lib. Here is a rough example how you could use an array of function pointers in each class to point at the functions: //Compilable code , hopefully. enum types{T1,T2,T3}; /*for example T1=DenseMatr T2=DiamondMatr T3=HybridMatr*/ class Matr{ public: Matr(){} virtual ~Matr(){} virtual Matr& _add(Matr*,types)=0{return *this;} virtual Matr& Add(Matr*){return *this;} virtual Matr& Add(Matr*, Matr*) {return *this;} }; /*function declarations*/ Matr* T1addT1(Matr* p1, Matr* p2); Matr* T1addT2(Matr* p1, Matr* p2); Matr* T1addT3(Matr* p1, Matr* p2); typedef Matr* (*FP)(Matr*,Matr*); class DenseMatr public: FP fp[3]; /*lib contains 3 types of Matrix at time of writing */ /*so DenseMatrix need to be able to add 3 types including itself? */ int f_count; types T; DenseMatr():T(T1),f_count(2){ fp[0]= T1addT1; fp[1]= T1addT2; fp[2]= T1addT3; /*obviously critical that the correct function is assigned to FP when writing code*/ } virtual ~DenseMatr(){} Matr& _add(Matr* arg, types t){ if(t<f_count) fp[t](this,arg); /*if this class knows about arg type*/ else arg->Add(this); /*if arg type is an afterthought it should*/ /*provide add functionality for this type*/ return *this; } }; /*bare class*/ class DiamondMatr public: FP fp; types T; DiamondMatr():T(T2){} virtual ~DiamondMatr(){} Matr& _add(Matr* arg, types T){ return *this;} }; /*bare class*/ class HybridMatr public: FP fp; types T; HybridMatr():T(T3){} virtual ~HybridMatr(){} Matr& _add(Matr* arg, types T){ return *this;} }; class Matr1 public: Matr1(){} ~Matr1(){} Matr1(const Matr1& rhs){} Matr1& Add(Matr* arg){ arg->_add(this,T); return *this; } Matr1& Add(Matr* p1, Matr* p2){ Add(&(p1->Add(p2))); return *this; } }; Matr* T1addT1(Matr* p1, Matr* p2){ static_cast<DenseMatr*>(p1); static_cast<DenseMatr*>(p2); /*Do addition*/ return p1; } Matr* T1addT2(Matr* p1, Matr* p2){ static_cast<DenseMatr*>(p1); static_cast<DiamondMatr*>(p2); /*Do addition*/ return p1; } Matr* T1addT3(Matr* p1, Matr* p2){ static_cast<DenseMatr*>(p1); static_cast<HybridMatr*>(p2); /*Do addition*/ return p1; } int main(int argc, char *argv[]) { Matr* m01 = new Matr1; Matr* m02 = new Matr1; m01->Add(m02,m01); delete m01; delete m02; return 0; } I know it's rough but it's a bit complicated and needs a fair bit of work to be made complete. > > > which is obviously inconvenient, and also invalidates the idea > > > of polymorphism, as the run type of the objects must be known > > > at compile time. In addition any extension of the library becomes > > > difficult, because if I define a new matrix type, together with > > > new Add() variants needed for it, the new Add() functions will > > > not be known as friends of the respective classes in the library. > > I agree that type casting is not a godd way, also templates are ruled > > out. > > Extensibility should and could be preserved using the method I tried > > to describe above using polyorphism. > > > > > Implementing Add() as a class method would also be difficult, because > > > there would have to be many overloaded variants in every class, the number > > > increasing with every new derived class. > > > > Yes I see this, this rules out global and class methods. > > > > > > > > > A possible alternative might be to define one global function > > > > > > void Add(Matr *A, Matr *B, Matr *C); > > > > > > (or class method), and perform the run-time type checking within this > > > function. This would require having several if-else options within the > > > function. However this solution appears not very elegant, again somewhat > > > inconsistent with the idea of the polymorphism, and similarly hard to > > > extend on new matrix types (apart from being likely inefficient). > RTTI doesn't sound like a good option. > > > > > > > > > In view of the above, my question is: > > > > > > What else can be done, using C++ capabilities, to allow me > > > just to write > > > > > > Add(A, B, C); > > > > > > and at the same time be able to extend the library > > > without having to make changes in the library? > > I'm not sure if I explained properly because I have a few grey areas > > about your design goals as described above, best I can see at present > > is to create a pure virtual Add() which takes one parameter and > > returns an object. Then dependant on your design goals overload this > > to accept more parameters with each overloaded version calling the > > virtual single parameter implementation of each parameter bar the last > > with the argument of the parameter in the parameter list. > > Then perhaps this can be improved upon to remove the returned object > > for design goal and/or efficiency reasons. > > > > > To sum up my patchy explanations will something like this help: > > > > class Matr{ > > virtual Matr& Add(Matr&)=0{return *this} > > }; > > > > class Matr1:Matr{ > > virtual Matr& Add(Matr*); > > virtual Matr& Add(Matr*, Matr*); > > virtual Matr& Add(Matr*, Matr*, Matr*); > > }; > > > > Matr& Matr1::Add(Matr* arg){ > > //do add stuff > > return *this; > > } > > > > Matr& Matr1::Add(Matr* arg1, Matr* arg2){ > > this->Add(arg1->Add(arg2)); > > return *this; > > } > > > > Matr& Matr1::Add(Matr* arg1, Matr* arg2, Matr* arg3){ > > this->Add(arg1->Add(arg2->Add(arg3))); > > } > > > > usage: > > Matr* mp_array[5] = {new Matr1, new Matr1, new Matr1, new Matr1,new > > Matr1}; > > > > mp_array[0]->Add(mp_array[1],mp_array[2],mp_array[3]); > > > > etc etc. > > > > ------------------------------------------- > To express my problem more rigorously, I now think this is an example > of the "multiple dispatch" problem, as described by > Scott Meyers in "More Effective C++", Addison-wesley, 1996, p. 228. > Unfortunately, he focused on the remedies for the unary operation > case, such as > > C = A > > whereas I need binary (and multi-operand, as you indicated, operations). > I also think that his proposal may not be very efficient, as the > lookup procedure involves std::map searches, which I expect to be rather > slow. > > Hence, I can reformulate my question: where can I find descriptions > of how to handle the multiple dispatch problem efficiently and > effectively in the case of binary and multi-operand operations. > > > Sincerely, > > L.B. > > > *-------------------------------------------------------------------* > | Dr. Leslaw Bieniasz, | > | Institute of Physical Chemistry of the Polish Academy of Sciences,| > | Department of Electrochemical Oxidation of Gaseous Fuels, | > | ul. Zagrody 13, 30-318 Cracow, Poland. | > | tel./fax: +48 (12) 266-03-41 | > | E-mail: | > *-------------------------------------------------------------------* > | Interested in Computational Electrochemistry? | > | Visit my web site: http://www.cyf-kr.edu.pl/~nbbienia | > *-------------------------------------------------------------------* I have never read the book you mention above. Sorry can't help you there. Paul. |
|
|
|
|
|||
|
|||
| Paul |
|
|
|
| |
![]() |
| Thread Tools | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| inheritance, list of objects, polymorphism | barbaros | C++ | 28 | 12-19-2009 02:18 PM |
| Dynamic polymorphism vs. Static polymorphism | Krivenok Dmitry | C++ | 13 | 06-01-2006 09:49 AM |
| stand-alone JMS, other JDBC operations, and transactions ( ActiveMQ + JOTM + JDBC operations ) | Jesus M. Salvo Jr. | Java | 2 | 02-11-2006 06:33 PM |
| Binary File Operations | Jeremy Robbins | Perl | 0 | 07-14-2004 09:45 PM |
| Binary Operations | MarcoGT | Java | 4 | 02-28-2004 11:06 AM |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc..
SEO by vBSEO ©2010, Crawlability, Inc. |




