簡體   English   中英

如果派生的 class 覆蓋該方法,為什么會調用基本 class 方法?

[英]Why is the base class method called if the derived class overrides the method?

考慮以下程序:

class Base {
public:
    virtual void foo() const {
        cout << "Base::foo()" << endl;
    }
};

class Derived : public Base {
public:
    virtual void foo() {
        cout << "Derived::foo()" << endl;
    }
};

void func(Base& obj) {
    obj.foo();
}

void main() {
    Derived d;
    func(d); // Base::foo() is printed 
}

如果我從Base class foo方法中刪除const ,則調用Derived::foo() 我似乎無法理解這種行為。

1)這種行為的原因是什么?

2)這是在編譯時還是運行時決定的?

謝謝

在派生的 class 中,function 簽名是這樣的:

virtual void foo(); //Derived::foo

其中沒有提到const 它是一個非常量成員 function,而Base::foo是一個const成員 function。 它們是兩個不同的函數,因為const是 function 簽名的一部分。

virtual void foo() const; //Base::foo 

派生的 class 不會覆蓋此 function,而是添加另一個 function。

所以修復是這樣的:

class Derived : public Base {
public:
    virtual void foo() const {
        cout << "Derived::foo()" << endl;
    }
};

因為const是 function 簽名的一部分。 所以當你打算覆蓋 base 的 foo 時必須提到它。


@davka 問道:

那么為什么選擇常量版本而不是非常量版本? 是否有任何規則,或者它恰好是第一個選擇?

這是因為objstatic類型是Base ,而 function 名稱是基於 ZA81259CEF8E959C624ZDF1D456E5D3297Z45B66A8CFDE8913AC1 的類型解析的 Base甚至沒有非常量版本。 所以不存在被選中或拒絕的問題。 它一開始在Base中不存在。

void func(Base& obj) {
    obj.foo();  //calls Base::foo
}

但是,如果將上面的代碼更改為以下內容:

void func(Derived & obj) {
    obj.foo();  //calls Derived:foo
}

現在將選擇非常量版本,因為Base::foo隱藏在Derived class 中。


由於Derived::foo隱藏了Base::foo ,因此您不能使用Derived的實例調用后者。

現在,讓我們取消隱藏Base::foo並做更多的實驗。

class Derived : public Base {
public:
    using Base::foo;         //<----------------this unhides Base::foo
    virtual void foo() {
        cout << "Derived::foo()" << endl;
    }
};

現在在 Derived 中,兩個函數(const 和 non-const 版本)都可用,未隱藏。 現在有幾個有趣的問題。

既然現在 Derived 已經隱藏了這兩個函數,那么下面的每個 function 會調用哪個 function?

void f(Derived& obj) {
    obj.foo(); //Which function? Base::foo or Derived::foo?
}
void g(const Derived & obj) {
    obj.foo(); //Which function? Base::foo or Derived::foo?
}

第一個將調用Derived::foo ,它是非常量版本,第二個將調用Base::foo ,它是 const 版本。 原因很簡單,使用 const object,只能調用const函數,但使用非 const 對象,兩者都可以調用,但如果可用,則選擇非 const 版本。

見在線演示: http://www.ideone.com/955aY

您沒有覆蓋該方法,因為Derived::foo並不完全相同。

要覆蓋方法,基本版本和覆蓋版本必須相同,包括const -ness。

在 C++ 中,您可以擁有兩個具有相同名稱和相同參數的函數,其中唯一的區別是一個是const ,一個不是。

這個想法是你有時想要不同的行為。 例如,訪問 function function 可能具有不同的返回類型:

class MyClass
{
public:
  virtual Xxx * GetXxx();
  virtual Xxx const * GetXxx() const;
  // ....
}

您可以單獨覆蓋這些函數。

在您的情況下,當您從非常量 object 調用foo時,您調用了 function 的非常量變體。 由於您已經覆蓋了 const-variant,所以基礎 class 中的那個就是被調用的那個。

您正在做的事情稱為“重載”。 正如@SLaks 指出的那樣,在覆蓋時,簽名需要相同。

const是簽名的一部分。 void foo() const是與void foo()不同的 function 。 你根本沒有壓倒一切。 這就是為什么。

暫無
暫無

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

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