-
October 29th, 2010, 10:40 AM
#1
Override different part of member functions in different derived classes
This the problem I am facing. I have a Base class which has several virtual functions declared and defined. I also have several Derived classes inherited from Base. Each derived class wants to override only some of the member functions of Base. And the sets of member functions to override by different derived classes are different. Maybe the following code explains better:
/////////////////////////////////////////////////////////////////////
/// Solution A
class Base
{
public:
Base(int i, int j) {}
virtual void funcA() {//do something in funcA}
virtual void funcB() {//do something in funcB}
virtual void funcC() {//do something in funcC}
virtual ~Base() {}
};
class Derived1 : public Base
{
public:
Derived1(int i, int j) : Base(i, j) {}
virtual void funcA() {// override funcA}
};
class Derived2 : public Base
{
public:
Derived2(int i, int j) : Base(i, j) {}
virtual void funcB() {// override funcB}
virtual void funcC() {// override funcC}
};
// More derived classes possible
/////////////////////////////////////////////////////////////////////
The above code is ok and did what I wanted. But there are a few drawbacks also. First, because C++ does not have constructor forwarding yet, we have to tediously call Base constructor in each derived classes constructor. Second, it's tedious to give different names to those derived classes, especially when there's a clear naming rule (e.g. "Derived" followed by an integer).
So I thought class template may be a good solution, as follows:
////////////////////////////////////////////////////////////
/// Solution B
template <int i>
class Derived : public Base
{
public:
Derived1(int i, int j) : Base(i, j) {}
virtual void funcA() { Base::funcA(); }
virtual void funcB() { Base::funcB(); }
virtual void funcC() { Base::funcC(); }
};
// Then specialize a member function if needed:
void Derived<1>::funcA() { // override funcA }
void Derived<2>::funcB() { // override funcB }
void Derived<2>::funcC() { // override funcC }
///////////////////////////////////////////////////////////
This way I solved the two problems mentioned above. The only thing I don't like is:
virtual void funcX() { Base::funcX(); } // "X" could be A, B or C
This has to be done because to be able to override it, I have to declare it in the derived class. But because not all derived classes will override all member functions, I have to provide a default definition for them (calling Base class implementations). I kind of feel this may cause an overhead of two indirections, am I right?
Now comes my question: Is something as follows possible? I know the following won't compile, but is looking for something as simple but valid.
//////////////////////////////////////////////////////
/// Solution C : ideal case, but not practical???
template <int i>
class Derived : public Base
{
public:
Derived1(int i, int j) : Base(i, j) {}
// Do not declare functions, use them from Base class if needed...
};
// But still be able to specialize a member function if needed:
void Derived<1>::funcA() { // override funcA }
void Derived<2>::funcB() { // override funcB }
void Derived<2>::funcC() { // override funcC }
/////////////////////////////////////////////////////////
Thanks!
-
October 29th, 2010, 12:10 PM
#2
Re: Override different part of member functions in different derived classes
Originally Posted by shawnwang
Second, it's tedious to give different names to those derived classes, especially when there's a clear naming rule (e.g. "Derived" followed by an integer).
If a class has a clear purpose, it shouldn't be that hard to give it a good name. A name like Derived1 is utterly meaningless and should IMO never be used in anything but a trivial example. The same goes for Derived<1>, of course.
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
-
October 29th, 2010, 01:00 PM
#3
Re: Override different part of member functions in different derived classes
Originally Posted by D_Drmmr
If a class has a clear purpose, it shouldn't be that hard to give it a good name. A name like Derived1 is utterly meaningless and should IMO never be used in anything but a trivial example. The same goes for Derived<1>, of course.
Well, this is a trivial example. In the actually case, I have much more meaningful names, like:
CPolicy<H264Encoder>.
-
October 29th, 2010, 02:51 PM
#4
Re: Override different part of member functions in different derived classes
Have you considered using pointers to memberfunctions instead of virtual functions?
My syntax here is all wrong but I hope you get the idea
Code:
class Base
{
public:
Base(int i, int j)
{
functionA=&functA;
functionB=&functB;
functionC=&functC;
}
virtual ~Base() {}
// typedefs of the member functions (can never remember how to do this)
typedef ... FunctionA()
typedef ... FunctionB()
typedef ... FunctionC()
// calls private functions via pointers
void funcA(){functionA();}
void funcB(){functionB();}
void funcC(){functionC();}
protected:
// The pointers to the member functions.
FunctionA* functionA;
FunctionB* functionB;
FunctionC* functionC;
// The actual implementation:
private:
void functA();
void functB();
void functC();
};
Your other code could then set pointers to different functions.
Last edited by Zaccheus; October 29th, 2010 at 03:08 PM.
-
October 29th, 2010, 02:55 PM
#5
Re: Override different part of member functions in different derived classes
Originally Posted by Zaccheus
Have you considered using pointers to memberfunctions instead of virtual functions?
How? Please elaborate...
-
October 29th, 2010, 03:08 PM
#6
Re: Override different part of member functions in different derived classes
see above
I can tidy it up tomorrow if you can wait but its getting late here.
-
October 29th, 2010, 04:34 PM
#7
Re: Override different part of member functions in different derived classes
Not entirely sure how safe this is ...
Code:
class Base
{
public:
Base(int i, int j)
{
funcPtrA=&Base::funcImpA;
funcPtrB=&Base::funcImpB;
funcPtrC=&Base::funcImpC;
}
virtual ~Base() {}
// Calls private functions via pointers
void funcA(){ (this->*funcPtrA)(); }
void funcB(){ (this->*funcPtrB)(); }
void funcC(){ (this->*funcPtrC)(); }
protected:
// typedefs of the member functions
typedef void (Base::*FunctionA)();
typedef void (Base::*FunctionB)();
typedef void (Base::*FunctionC)();
// The pointers to the member functions.
FunctionA funcPtrA;
FunctionB funcPtrB;
FunctionC funcPtrC;
private:
// The base class' member functions:
void funcImpA(){}
void funcImpB(){}
void funcImpC(){}
};
class Derived : Base
{
public:
Derived() : Base(1,2)
{
funcPtrA = static_cast<FunctionA>( &Derived::funcImpAA );
}
private:
// The derived class' member functions:
void funcImpAA(){}
};
Last edited by Zaccheus; October 29th, 2010 at 04:42 PM.
-
October 29th, 2010, 06:18 PM
#8
Re: Override different part of member functions in different derived classes
Originally Posted by shawnwang
Now comes my question: Is something as follows possible? I know the following won't compile, but is looking for something as simple but valid.
To me it looks like you're using Base just to inherit implementation. You don't really need that in a template solution, like
Code:
template <int I>
class Derived {
public:
Derived(int, int) {}
void funcA() {std::cout << "A\n";} // standard implementations
void funcB() {std::cout << "B\n";}
void funcC() {std::cout << "C\n";}
};
void Derived<1>::funcA() {std::cout << "1, A\n";} // specializations ("overrides")
void Derived<2>::funcB() {std::cout << "2, B\n";}
void Derived<2>::funcC() {std::cout << "2, C\n";}
// usage somewhere else
Derived<0> d0(0,0); // no specialization
d0.funcA();
d0.funcB();
d0.funcC();
Derived<1> d1(0,0); // funcA specialized
d1.funcA();
d1.funcB();
d1.funcC();
Derived<2> d2(0,0); // funcB and funcC specialized
d2.funcA();
d2.funcB();
d2.funcC();
But if you want you can make Base a pure interface and let Derived inherit it,
Code:
class Base {
public:
virtual ~Base() {}
virtual void funcA() =0;
virtual void funcB() =0;
virtual void funcC() =0;
};
template <int I>
class Derived : public Base {
public:
Derived(int, int) {}
void funcA() {std::cout << "A\n";} // standard implementations
void funcB() {std::cout << "B\n";}
void funcC() {std::cout << "C\n";}
};
Derived then becomes a flexible implementation class for the Base interface which can be used polymorphically, like for example
Code:
Derived<1> d1(0,0); // use the Derived 1 implementation of the Base interface
Base* b1 = &d1; // (pointer assignment to avoid slicing)
b1->funcA(); // polymorphic call via Base pointer
b1->funcB();
b1->funcC();
So depending on the purpose you can use Derived as a template class in its own right. If Base was just a way to supply a common implementation you can as well drop it because it's not needed. But if Base is an important type in your design you can make it an interface and use Derived as a handy way to arrange for several implementations of it.
Last edited by nuzzle; October 30th, 2010 at 12:55 AM.
-
October 29th, 2010, 06:36 PM
#9
Re: Override different part of member functions in different derived classes
Originally Posted by shawnwang
The above code is ok and did what I wanted. But there are a few drawbacks also. First, because C++ does not have constructor forwarding yet, we have to tediously call Base constructor in each derived classes constructor. Second, it's tedious to give different names to those derived classes, especially when there's a clear naming rule (e.g. "Derived" followed by an integer).
Originally Posted by shawnwang
Well, this is a trivial example. In the actually case, I have much more meaningful names, like:
CPolicy<H264Encoder>.
It's not clear to me what the problem is.
You say it's tedious to give names to derived classes, yet you have meaningful names. Seems contradictory to me.
That leaves having to copy constructors, which doesn't seems like something that requires the introduction of an obscure design. Perhaps some sort of code generation is better suited.
From the code you posted, it looks like policy based design might provide a better solution than inheritance for you.
Cheers, D Drmmr
Please put [code][/code] tags around your code to preserve indentation and make it more readable.
As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky
-
October 30th, 2010, 08:18 AM
#10
Re: Override different part of member functions in different derived classes
Have a look at this, it uses only one derived class. You change the behaviour of funcA, funcB, funcC at run time.
Code:
#include <iostream>
class Base
{
public:
Base(int i, int j)
: x(i), y(j)
{
funcPtrA=&Base::funcImpA;
funcPtrB=&Base::funcImpB;
funcPtrC=&Base::funcImpC;
}
virtual ~Base() {}
// Public functions, call implementation via pointers
void funcA(char arg){ (this->*funcPtrA)(arg); }
void funcB(long arg){ (this->*funcPtrB)(arg); }
void funcC(float arg){ (this->*funcPtrC)(arg); }
// typedefs of the member functions
typedef void (Base::*FunctionA)(char arg);
typedef void (Base::*FunctionB)(long arg);
typedef void (Base::*FunctionC)(float arg);
void setFuncA(FunctionA func){funcPtrA = func;}
void setFuncB(FunctionB func){funcPtrB = func;}
void setFuncC(FunctionC func){funcPtrC = func;}
protected:
int x;
int y;
private:
// The pointers to the member functions.
FunctionA funcPtrA;
FunctionB funcPtrB;
FunctionC funcPtrC;
// The base class' member functions:
void funcImpA(char arg){ std::cout << "Base::funcImpA" << std::endl; }
void funcImpB(long arg){ std::cout << "Base::funcImpB" << std::endl; }
void funcImpC(float arg){ std::cout << "Base::funcImpC" << std::endl; }
};
class Derived : public Base
{
public:
Derived(int i, int j):Base(i,j){}
// The derived class' member functions:
void funcImpB1(long arg){ std::cout << "Base::funcImpB1" << std::endl; }
void funcImpB2(long arg){ std::cout << "Base::funcImpB2" << std::endl; }
};
void MemberfunctionDemo()
{
Derived original(1,2);
Derived someobj(3,4);
Derived another(5,6);
someobj.setFuncB(static_cast<Base::FunctionB>(&Derived::funcImpB1));
another.setFuncB(static_cast<Base::FunctionB>(&Derived::funcImpB2));
original.funcA('a');
original.funcB(1);
original.funcC(1.0);
someobj.funcA('a');
someobj.funcB(1);
someobj.funcC(1.0);
another.funcA('a');
another.funcB(1);
another.funcC(1.0);
}
-
October 30th, 2010, 08:45 AM
#11
Re: Override different part of member functions in different derived classes
note that in this code
Originally Posted by Zaccheus
Code:
someobj.setFuncB(static_cast<Base::FunctionB>(&Derived::funcImpB1));
another.setFuncB(static_cast<Base::FunctionB>(&Derived::funcImpB2));
dereferencing the converted member function pointers gives undefined behavior; you can only convert safely from a pointer to member of Base to a pointer to member of Derived ( and even in this case provided Base is non virtual and non ambiguous, if I remember well ).
-
October 30th, 2010, 09:13 AM
#12
Re: Override different part of member functions in different derived classes
Yeah I was worried about that (hence the comment in my 1st post) kind of stuff, for example what happens with the 'this' pointer if Derived uses multiple inheritance.
I thought it must be safe because what I do here is very similar to how Microsoft have implemented their Windows message map in MFC. I'll have another look at that maybe.
A safe alternative would be to use static member functions which take a pointer to the object as their first parameter, but then the derived class does not have access to the protected parts of Base.
-
October 30th, 2010, 02:51 PM
#13
Re: Override different part of member functions in different derived classes
This solution works but it is ludicrously complicated.
There is one base class and one derived class. The base class has all the default behaviour and the derived class has all the specialised versions of the base class' overridable functions. You override a base class function on a specific instance of the derived class by calling the corresponding setFuncX function and passing it a pointer to the specialised function. See the MemberfunctionDemo() function.
To be honest I think it would be simpler to just invent lots of derived names and live with the small task of writing the code which calls the base class, but it has been fun to come up with this solution.
Code:
#include <iostream>
class Base
{
public:
Base(int i, int j)
: x(i), y(j)
{
}
virtual ~Base() {}
// Public functions.
inline void funcA(char arg){ funcImpA(arg); }
inline void funcB(long arg){ funcImpB(arg); }
inline void funcC(float arg){ funcImpC(arg); }
protected:
// The base class' member functions:
virtual void funcImpA(char arg){ std::cout << "Base::funcImpA: " << arg << std::endl; }
virtual void funcImpB(long arg){ std::cout << "Base::funcImpB: " << arg << std::endl; }
virtual void funcImpC(float arg){ std::cout << "Base::funcImpC: " << arg << std::endl; }
private:
int x;
int y;
};
class Derived : public Base
{
public:
Derived(int i, int j):Base(i,j)
{
funcPtrA=&Derived::funcDefA;
funcPtrB=&Derived::funcDefB;
funcPtrC=&Derived::funcDefC;
}
// typedefs of the member functions
typedef void (Derived::*FunctionA)(char arg);
typedef void (Derived::*FunctionB)(long arg);
typedef void (Derived::*FunctionC)(float arg);
void setFuncA(FunctionA func){funcPtrA = func;}
void setFuncB(FunctionB func){funcPtrB = func;}
void setFuncC(FunctionC func){funcPtrC = func;}
// Default behaviour.
void funcDefA(char arg){ Base::funcImpA(arg); }
void funcDefB(long arg){ Base::funcImpB(arg); }
void funcDefC(float arg){ Base::funcImpC(arg); }
// The derived class' member functions:
void funcImpB1(long arg){ std::cout << "Derived::funcImpB1: " << arg << std::endl; }
void funcImpB2(long arg){ std::cout << "Derived::funcImpB2: " << arg << std::endl; }
protected:
virtual void funcImpA(char arg){ (this->*funcPtrA)(arg); }
virtual void funcImpB(long arg){ (this->*funcPtrB)(arg); }
virtual void funcImpC(float arg){ (this->*funcPtrC)(arg); }
private:
// The pointers to the member functions.
FunctionA funcPtrA;
FunctionB funcPtrB;
FunctionC funcPtrC;
};
void MemberfunctionDemo()
{
Derived original(1,2);
Derived someobj(3,4);
Derived another(5,6);
someobj.setFuncB(&Derived::funcImpB1);
another.setFuncB(&Derived::funcImpB2);
original.funcA('a');
original.funcB(1);
original.funcC(1.0);
someobj.funcA('b');
someobj.funcB(2);
someobj.funcC(2.0);
another.funcA('c');
another.funcB(3);
another.funcC(3.0);
}
-
November 1st, 2010, 09:33 AM
#14
Re: Override different part of member functions in different derived classes
Originally Posted by nuzzle
To me it looks like you're using Base just to inherit implementation. You don't really need that in a template solution, like
Code:
template <int I>
class Derived {
public:
Derived(int, int) {}
void funcA() {std::cout << "A\n";} // standard implementations
void funcB() {std::cout << "B\n";}
void funcC() {std::cout << "C\n";}
};
void Derived<1>::funcA() {std::cout << "1, A\n";} // specializations ("overrides")
void Derived<2>::funcB() {std::cout << "2, B\n";}
void Derived<2>::funcC() {std::cout << "2, C\n";}
// usage somewhere else
Derived<0> d0(0,0); // no specialization
d0.funcA();
d0.funcB();
d0.funcC();
Derived<1> d1(0,0); // funcA specialized
d1.funcA();
d1.funcB();
d1.funcC();
Derived<2> d2(0,0); // funcB and funcC specialized
d2.funcA();
d2.funcB();
d2.funcC();
Yes, this is a neat solution. The only problem with this one is that in some of the specialization, I'd like to use the default implementation first and then do some extra stuff. So I need something like
Code:
void Derived<1>::funcA() {
Derived<default int>::funcA(); // calling default implementation
std::cout << "1, A\n"; // do some extra work
} // specializations ("overrides")
I am thinking of using an implementation class to do the concrete work and call its members in the default implementation of Derived class. In specializations of member functions, we can also call the member of implementation class first then do extra work.
Code:
class Implementation {
public:
Implementation(int, int) {}
funcAImpl() {std::cout << "A\n";} // standard implementations
funcBImpl() {std::cout << "B\n";}
funcCImpl() {std::cout << "C\n";}
};
template <int I>
class Derived {
public:
Derived(int i, int j) : m_implementation(i, j) {}
void funcA() {m_implementation.funcAImpl();} // standard implementations
void funcB() {m_implementation.funcBImpl();}
void funcC() {m_implementation.funcVImpl();}
private:
Implementation m_implementation;
};
void Derived<1>::funcA() { // call default implementation first and then do extra work
m_implementation.funcAImpl();
std::cout << "1, A\n";
}
void Derived<2>::funcB() { // call default implementation first and then do extra work
m_implementation.funcBImpl();
std::cout << "2, B\n";
}
void Derived<2>::funcC() {std::cout << "2, C\n";} // full specialization; do not call default implementation
Last edited by shawnwang; November 1st, 2010 at 09:43 AM.
-
November 1st, 2010, 09:47 AM
#15
Re: Override different part of member functions in different derived classes
Originally Posted by Zaccheus
To be honest I think it would be simpler to just invent lots of derived names and live with the small task of writing the code which calls the base class...
Agreed. After looking around for better (cleaner) solutions and didn't find a clear winner, having a lot of derived names and copying the constructors don't seem that ugly any more. And the best part of this solution is that it's simple. Simplest is the best...
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|