![](/img/trans.png)
[英]Why can't I call protected virtual base class function in the derived class overridden function?
[英]Can a base class know if a derived class has overridden a virtual method?
對於C#存在相同的問題,但不適用於C ++。
class Base
{
void dispatch()
{
if (newStyleHasBeenOverridden()) //how to find this out?
newStyle(42);
else
oldStyle(1, 2);
}
virtual void oldStyle(int, int) { throw "Implement me!"; }
virtual void newStyle(int) { throw "Implement me!"; }
}
class Derived:public Base
{
void newStyle(int) override
{
std::cout<<"Success!";
}
}
警告 :此解決方案不是跨平台的,因為它依賴於GCC擴展和某些未定義的行為。
GCC允許語法通過說this->*&ClassName::functionName
從this
的vtable中獲取指向函數的指針。 實際使用它可能不是一個好主意,但是無論如何這是一個演示:
#include <iostream>
class Base {
public:
void foo() {
auto base_bar_addr = reinterpret_cast<void*>(&Base::bar);
auto this_bar_addr = reinterpret_cast<void*>(this->*&Base::bar);
std::cout << (base_bar_addr == this_bar_addr ? "not overridden" : "overridden") << std::endl;
}
virtual void bar() { };
};
class Regular : public Base { };
class Overriding : public Base {
public:
virtual void bar() { };
};
int main() {
Regular r;
r.foo();
Overriding o;
o.foo();
}
對於后代:
&Base::bar
,因此您始終會認為它沒有被覆蓋。 這是一個設計問題。
但是,為了回答實際問題,有兩種方法可以完成此任務而無需重新設計(但實際上,您應該重新設計它)。
一種(可怕的)選擇是調用newstyle方法,並捕獲未覆蓋的異常。
void dispatch() {
try {
newStyle(42);
} catch (const char *) {
oldStyle(1, 2);
}
}
如果newStyle已被覆蓋,則將調用覆蓋。 否則,將拋出基本實現,該調度將捕獲,然后回退到oldStyle。 這是對異常的濫用,並且性能會很差。
另一種(稍差一些)的方法是將newStyle的基本實現轉發到oldStyle。
void dispatch() {
newStyle(42);
}
virtual void newStyle(int) { oldStyle(1, 2); }
virtual void oldStyle(int, int) { throw "implement me"; }
這至少朝着更好的設計方向發展。 繼承的重點是允許高級代碼能夠互換使用對象,而不管其專業性如何。 如果調度員必須檢查實際的對象類型,則您違反了《里斯科夫替代原理》。 調度應該能夠以相同的方式處理所有對象,並且行為上的任何差異都應由重寫的方法本身引起(而不是存在重寫)。
使事情變得更簡單的是, Derived
決策由Derived
類完成。
抽象Base
類基本上只是一個“接口”, Derived
類應在其中實現所有 virtual
函數。
這個問題聽起來也像是XY問題。
我以為這就是你想要的:
class Base // abstract class
{
virtual void oldStyle(int, int) = 0; // pure virtual functions
virtual void newStyle(int) = 0; // needs to be implemented
};
class Derived:public Base
{
public:
Derived(bool useNewStyle): _useNewStyle(useNewStyle) {}
void newStyle(int) { std::cout << "new style"; }
void oldStyle(int, int) { std::cout << "old style"; }
void dispatch()
{
if (_useNewStyle) {
newStyle(42);
return;
}
oldStyle(1, 2);
return;
}
private:
bool _useNewStyle = false;
};
Derived d(true); // use new style
d.dispatch(); // "new style"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.