[英]C++ Inheritance accessing a non-virtual function in derived class from base class pointer
[英]C++ same name for non-virtual function in derived class conflicts with `final` specifier
這有一個完整的新手問題的感覺,但是當將final
說明符用於B::operator()
時,為什么以下代碼沒有編譯?
struct A
{
virtual void operator()() const = 0;
};
// the CRTP-component is not really necessary here
// but it possibly makes more sense in that it could be applied like this in reality
//
template<typename Derived>
struct B : A
{
virtual void operator()() const override final
{
static_cast<Derived const&>(*this).operator()();
}
};
struct C : B<C>
{
void operator()() const
{
//do something
}
};
int main()
{
C()();
}
G ++打印以下錯誤消息 :
main.cpp:17:14: error: virtual function 'virtual void C::operator()() const'
void operator()() const
^
main.cpp:9:22: error: overriding final function 'void B<Derived>::operator()() const [with Derived = C]'
virtual void operator()() const override final
^
我會以為它可以工作,因為非虛擬C::operator()
不會在其基類中覆蓋虛擬函數? 我如何才能使用它(在不更改C::operator()
名稱的情況下)?
編輯 :正如幾個用戶所指出的,答案很簡單,派生類中的virtual
-keyword是多余的(而我認為將其保留會阻止繼承)。 但是,我提出這個目標的目的是在整個動態和靜態繼承層次結構中實現一致的接口,可以通過在整個過程中使用非虛擬operator[]
來解決,並通過一個虛擬函數apply
耦合類A
和B
:
struct A
{
void operator()() const
{
this->apply();
}
protected:
virtual void apply() const = 0;
};
template<typename Derived>
struct B : A
{
void operator()() const
{
static_cast<Derived const&>(*this).operator()();
}
protected:
virtual void apply() const override final
{
this->operator()();
}
};
struct C : B<C>
{
void operator()() const
{
//do something
}
};
int main()
{
C()();
}
如果在基類中將函數聲明為virtual
函數,則無論您是否使用virtual
關鍵字,在派生類中聲明具有相同名稱和參數列表的函數都是隱式virtual
函數。 您不能使C::operator()()
是非虛擬的。
派生類中的功能與基類中的虛函數具有相同簽名的函數會覆蓋基類中的虛函數。 即使/盡管派生類中的聲明不使用virtual
關鍵字,這也使其成為虛擬函數。
這是無法更改的,因此,如果您確實需要在派生類中擁有一個具有相同名稱的函數,並且該函數不覆蓋基類中的虛函數(並且在此過程中,請成為虛函數本身,在這種情況下,違反B
的final
),您需要在派生類中更改函數的簽名。 這可能意味着不同的名稱,不同的參數列表或不同的限定詞。 不過,我會非常謹慎地對待后兩者-編譯器將能夠整理出您造成的混亂,但是許多人類讀者可能(非常容易)感到驚訝。
如果我正在審查這樣的代碼,可能會把它當作一個問題,並且作者將需要提供非常扎實的理由,說明為何確實有必要使它獲得批准。
作為覆蓋(因為它與基類中的虛函數具有相同的簽名),所以覆蓋與基類中指定的final
沖突。
一種解決方法(或更確切地說,解決方法)是為該函數提供默認參數,以使其具有不同的類型,因此不能覆蓋,更好的方法是修復設計。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.