Calling derived class function from base class

前端 未结 2 721
悲&欢浪女
悲&欢浪女 2020-12-03 05:46
class base
{
  public:
  virtual void start();
  virtual void stop();

  void doSomething() { start(); .... stop(); }
}

class derived : public base
{
  public:
   v         


        
相关标签:
2条回答
  • 2020-12-03 06:14

    Update
    Based on your comment below that you are trying to make doSomething() call the Derived class's version of start() and stop(), my updated answer to your question is as follows:

    There is nothing wrong with the way that you defined Base and Derived. You are probably experiencing what is called "code slicing", where you are calling "doSomething()" on an object whose declared type is "Base", instead of "Base*" or "Base&", which will result in the object being converted to type Base.

    Bad example:

     Derived derived;
     Base base = derived;
     base.doSomething();  // This is Base's version of doSomething()
    

    Good example:

     Base* base = new Derived;  // NOTE: declared type is "Base*"
     base->doSomething();  // This will call Derived version
     delete base;
    

    Side-note: you should use a scoped_ptr, shared_ptr, unique_ptr, or some other smart pointer class instead of using a pointer directly as in my example; however, to not obscure the issue, I have opted to use a raw pointer in this example. For more information about "slicing", see:

    • What is the slicing problem in C++? - StackOverflow
    • Slicing in C++

    Original solution
    You could do something like this:

    class Base {
        public:
            Base() {}
            virtual ~Base() {}
    
            virtual void start() {
               startInternal();
            }
    
            virtual void stop() {
                stopInternal();
            }
    
            void doSomething() {
                startInternal();
                // ...
                stopInternal();
            }
        private:
            void startInternal() {
              // ...
            } 
            void stopInternal() {
              // ...
            }
    };
    
    class Derived : public Base {
        public:
            Derived() {}
            virtual ~Derived() {}
            virtual void start() {
                // ...
            }
            virtual void stop() {
                // ...
            }
    };
    

    If you do this, then doSomething() will use the internal version of start/stop which isn't overridden. You will find this pattern a lot, when a constructor/destructor needs to share logic with a virtual method.

    Also, not related to the issue at hand, don't forget that you should always create a virtual destructor whenever you create a class that has virtual methods.

    0 讨论(0)
  • 2020-12-03 06:15

    The code you've posted should work the way you want. Calling doSomething on an instance of derived will call the overridden start and stop functions defined in derived.

    There's an exception to that, though. If you call doSomething in the constructor or destructor of base (whether directly or indirectly), then the versions of start and stop that get called will be the ones defined in base. That's because in those circumstances, you don't actually have a valid derived instance yet. It's either not fully constructed or partially destructed, so the language prevents you from calling methods that would use the partial object.

    If you're not calling it from a base constructor or destructor, then there is more to the problem than what's shown here.

    0 讨论(0)
提交回复
热议问题