簡體   English   中英

從基類調用派生類函數

[英]Calling derived class function from base class

class base
{
  public:
  virtual void start();
  virtual void stop();

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

class derived : public base
{
  public:
   void start();
   void stop();
}

但是當我在派生類中調用doSomething() ,它使用它自己的Start()Stop() - 而不是派生類。

我不想在派生類中重寫doSomething() ,因為它與基類相同。 我究竟做錯了什么?

對不起,如果不清楚。
派生類中Start()和Stop()的行為是不同的(它是一個不同的機器) - 但我想使用原始基類doSomething(),因為它沒有改變。 它只需要使用新的派生類代碼start()和stop()。

您發布的代碼應該按照您想要的方式工作。 derived的實例上調用doSomething將調用在derived定義的重寫的startstop函數。

但是有一個例外。 如果你在base的構造函數或析構函數中調用doSomething (無論是直接還是間接),那么被調用的startstop版本將是base定義的版本。 那是因為在這種情況下,你實際上還沒有一個有效的derived實例。 它不是完全構造的或部分破壞的,因此該語言阻止您調用將使用部分對象的方法。

如果你沒有從base構造函數或析構函數中調用它,那么問題就比這里顯示的更多了。

更新
根據您在下面的評論,您試圖讓doSomething()調用Derived類的start()和stop()版本,我對您的問題的更新答案如下:

您定義Base和Derived的方式沒有任何問題。 您可能正在經歷所謂的“代碼切片”,您在聲明類型為“Base”的對象上調用“doSomething()”,而不是“Base *”或“Base&”,這將導致對象成為轉換為Base類型。

不好的例子:

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

好例子:

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

注意:你應該使用scoped_ptr,shared_ptr,unique_ptr或其他一些智能指針類,而不是像我的例子那樣直接使用指針; 但是,為了不掩蓋這個問題,我選擇在這個例子中使用原始指針。 有關“切片”的更多信息,請參閱:

原始解決方案
你可以這樣做:

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() {
            // ...
        }
};

如果你這樣做,那么doSomething()將使用未被覆蓋的內部版本的start / stop。 當構造函數/析構函數需要與虛方法共享邏輯時,您會發現很多這種模式。

此外,與手頭的問題無關,不要忘記每當創建具有虛方法的類時,都應始終創建虛擬析構函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM