[英]Private virtual function of base is hidden by private virtual function of derived
[英]Override public virtual function with private base function?
讓我們考慮具有以下接口的兩個類A
和B
:
class A {
public:
virtual void start() {} //default implementation does nothing
};
class B {
public:
void start() {/*do some stuff*/}
};
然后是第三個繼承自兩者的類, A
公開,因為它實現了這個“接口”, B
私有,因為這是實現細節。
然而,在這個特定的實現中, start()
只需要包含對B::start()
的調用。 所以我想我可以使用快捷方式並執行以下操作:
class C: public A, private B {
public:
using B::start;
};
並完成它,但顯然它不起作用。 因此,我無法using
私有基函數來覆蓋虛擬。 由此,兩個問題:
start()
函數在C
具有完全相同的簽名,但編譯器似乎對它很好,並且只調用A::start()
。編輯:一些精度:
A
指針操作C
對象。B::start()
的簡單函數,我特別想知道 using 聲明是否確實可以“覆蓋”虛擬,如果不能,如何允許這兩個函數共存。virtual
繼承之類的東西。是否有任何方法可以使這項工作,因為我認為它可能有效?
你應該覆蓋成員函數並顯式調用B::start()
:
class C: public A, private B {
public:
void start() override { B::start(); }
};
為什么編譯器會接受此代碼有效? 正如我所看到的,現在有兩個
start()
函數在C中具有完全相同的簽名,但編譯器看起來很好並且只調用A::start()
。
你是對的,有兩個成員函數可以在C( A::start()
和B::start()
)中訪問。 並且在class C
,沒有通過using ...::start()
覆蓋start()
或使任何基類的start()
可見,當嘗試使用unqalified調用成員函數時,將會出現歧義錯誤來自C
對象的namelookup。
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
};
int main(){
A* a = new C();
a->start(); //Ok, calls A::start()
C* c = new C();
c->start(); //Error, ambiguous
}
要解決此問題,您必須使用限定名稱,例如:
C* c = new C();
c->A::start(); //Ok, calls A::start()
現在,在class C
using B::start()
只需聲明start()
以引用B::start()
只要從C
的對象使用此名稱即可
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
public:
using B::start();
};
int main(){
A* a = new C();
a->start(); //Ok, calls A::start()
C* c = new C();
c->start(); //Ok, calls B::start()
}
using B::start
使函數void B::start()
在C
可見,它不會覆蓋它。 要調用make所有上面的非限定成員函數調用,要調用B::start()
,你應該覆蓋C
的成員函數,並使其調用B::start()
class A {
public:
virtual void start() { std::cout << "From A\n"; }
};
class B {
public:
void start() { std::cout << "From B\n"; }
};
class C: public A, private B {
public:
void start() override { B::start(); }
};
int main(){
A* a = new C();
a->start(); //Ok, calls C::start() which in turn calls B::start()
// ^^^^^^^^^^^^^^^^ - by virtual dispatch
C* c = new C();
c->start(); //Ok, calls C::start() which in turn calls B::start()
}
我想你可能會混淆“公共”和“私人”的含義。 在C ++繼承上下文中,這僅僅意味着一切都知道'C'是'A',而對於'B'類型,只有其他'C'對象可以訪問'C'對象的父方法('B'方法) 。
第二部分是關於繼承歧義。 不 using B::start;
繼承確實是模糊的,不會編譯(當轉到c.start()
),所以實際上在你的例子中添加該語句不是可選的(使用A或B),如果你不想經常使用合格的路徑。
我不清楚你是否期望c()->start();
調用'A'方法或'B'方法,但using語句將根據您的需要確定它。 你編寫代碼的方式有點不確定 - “A” 真的需要開始嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.