[英]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返回類型的對象Base
或Derived
。
在這里,派生類的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.