簡體   English   中英

調用派生類的虛擬函數時獲得訪問說明錯誤,該派生類在基類中是私有的

[英]Getting access-specifier error while calling virtual function of derived class which is private in base class

為什么下面的代碼出現訪問說明錯誤(私有成員)?

#include<iostream>
using namespace std;

class Derived;

class Base {
private:
    virtual void fun() { cout << "Base Fun"; }
};

class Derived: public Base {
public:
    void fun() { cout << "Derived Fun"; } //this should be called
};

int main()
{
   Base *ptr = new Derived;
   ptr->fun();
   return 0;
}

在這里,派生類的fun()應該被調用,並且由於它是公共的,因此應該沒有錯誤。

根據標准( N4140 ):

11.5訪問虛擬功能

1虛擬函數的訪問規則(第11條)由其聲明確定,並且不受后來覆蓋該函數的函數規則的影響。 [ 示例

 class B { public: virtual int f(); }; class D : public B { private: int f(); }; void f() { D d; B* pb = &d; D* pd = &d; pb->f(); // OK: B::f() is public, // D::f() is invoked pd->f(); // error: D::f() is private } 

結束示例 ]

順便說一句,通常情況下,在編譯期間,BTW無法知道將在運行時調用哪個類。

考慮

Base *ptr = GetBaseOrDerivedObject();
ptr->fun();

其中GetBaseOrDerivedObject ,這取決於具體的運行時間的情況下,可以在poiner返回類型的對象BaseDerived

在這里,派生類的fun()應該被調用,並且由於它是公共的,因此應該沒有錯誤。

不幸的是,事實並非如此。

這有效:

 Derived *ptr = new Derived;
 ptr->fun();

這不起作用:

 Base *ptr = new Derived;
 ptr->fun();

原因很簡單: Base沒有名為fun公共成員,因此您不能通過指向Base的指針來訪問它。
您可以在派生類中為覆蓋的成員方法設置自己的可見性說明符,但這並不能神奇地提升基類的說明符。


存在一個稱為NVI非虛擬接口 )的眾所周知的成語,該成語主要基於此模式(基類中的私有虛擬成員方法)。
您可以將其想象為模板方法模式的改進,即使說實話這也不是事實。

暫無
暫無

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

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