CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Oct 2010
    Posts
    5

    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!

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Override different part of member functions in different derived classes

    Quote Originally Posted by shawnwang View Post
    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

  3. #3
    Join Date
    Oct 2010
    Posts
    5

    Re: Override different part of member functions in different derived classes

    Quote Originally Posted by D_Drmmr View Post
    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>.

  4. #4
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    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.
    My hobby projects:
    www.rclsoftware.org.uk

  5. #5
    Join Date
    Oct 2010
    Posts
    5

    Re: Override different part of member functions in different derived classes

    Quote Originally Posted by Zaccheus View Post
    Have you considered using pointers to memberfunctions instead of virtual functions?
    How? Please elaborate...

  6. #6
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    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.
    My hobby projects:
    www.rclsoftware.org.uk

  7. #7
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    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.
    My hobby projects:
    www.rclsoftware.org.uk

  8. #8
    Join Date
    May 2009
    Posts
    2,413

    Re: Override different part of member functions in different derived classes

    Quote Originally Posted by shawnwang View Post
    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.

  9. #9
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Override different part of member functions in different derived classes

    Quote Originally Posted by shawnwang View Post
    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).
    Quote Originally Posted by shawnwang View Post
    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

  10. #10
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    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);
    }
    My hobby projects:
    www.rclsoftware.org.uk

  11. #11
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Override different part of member functions in different derived classes

    note that in this code

    Quote Originally Posted by Zaccheus View Post
    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 ).

  12. #12
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    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.
    My hobby projects:
    www.rclsoftware.org.uk

  13. #13
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Talking 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);
    }
    My hobby projects:
    www.rclsoftware.org.uk

  14. #14
    Join Date
    Oct 2010
    Posts
    5

    Re: Override different part of member functions in different derived classes

    Quote Originally Posted by nuzzle View Post
    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.

  15. #15
    Join Date
    Oct 2010
    Posts
    5

    Re: Override different part of member functions in different derived classes

    Quote Originally Posted by Zaccheus View Post
    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
  •  





Click Here to Expand Forum to Full Width

Featured