也許更好的是:爲什麼標準要求在這些情況下轉發到基類? (耶 - 爲什麼 - 因爲?)標準中的哪些位置正在轉發到這些情況下所需的基類?
class B1 {
public:
virtual void f()=0;
};
class B2 {
public:
virtual void f(){}
};
class D : public B1,public B2{
};
class D2 : public B1,public B2{
public:
using B2::f;
};
class D3 : public B1,public B2{
public:
void f(){
B2::f();
}
};
D d;
D2 d2;
D3 d3;
MS給出:
sourceFile.cpp
sourceFile.cpp(24) : error C2259: 'D' : cannot instantiate abstract class
due to following members:
'void B1::f(void)' : is abstract
sourceFile.cpp(6) : see declaration of 'B1::f'
sourceFile.cpp(25) : error C2259: 'D2' : cannot instantiate abstract class
due to following members:
'void B1::f(void)' : is abstract
sourceFile.cpp(6) : see declaration of 'B
,同樣爲MS編譯器。
我可能購買第一種情況下,d。但是在D2-f中使用聲明定義的明確地爲,爲什麼這不足以滿足需要填充vtable的編譯器?
標準在哪裏這種情況下定義?
的效應初探添加回答
對於下面的答案我已經接受:
這個問題似乎不爲什麼在規範中的錯誤? - 如果有一個具有一系列非虛擬f()的繼承層次結構,派生類中的使用通過使用語句來確定,並且將基類中的f的decl改爲虛擬,那麼可以改變在派生類中調用f並使用語句來選擇它們的f。這是一個我不知道的C++「gotcha」。它可能是語言的一部分,但這種「遠距離行動」使我感到不安,對我來說似乎違反了某種正確性/維護原則(我現在還不能完全闡明)。
但是我可以舉一個例子:
#include <iostream>
using std::cout;
namespace NonVirtual_f{
class C0 {
public:
void f(){cout<<"C0::f()"<<'\n';}
};
class C1 : public C0{
public:
void f(){cout<<"C1::f()"<<'\n';}
};
class C2 : public virtual C1{
public:
void f(){cout<<"C2::f()"<<'\n';}
};
class D3 : public virtual C1, public C2{
public:
using C1::f;
};
}//namespace NonVirtual_f
namespace Virtual_f{
class C0 {
public:
virtual void f(){cout<<"C0::f()"<<'\n';}
};
class C1 : public C0{
public:
void f(){cout<<"C1::f()"<<'\n';}
};
class C2 : public virtual C1{
public:
void f(){cout<<"C2::f()"<<'\n';}
};
class D3 : public virtual C1, public C2{
public:
using C1::f;
};
}//namespace Virtual_f
int main(int argc,const char* const*argv){
NonVirtual_f::D3 nv3;
nv3.f();
Virtual_f::D3 v3;
v3.f();
return 0;
}
從那裏的輸出:
C1::f()
C2::f()
所有這些改變是在C0 f的虛擬性。特別地,一旦在基類f的非虛擬性被選擇,它不能在不維護問題改變,如果一些派生類(即在一般一個不能知道)已經「被覆蓋」如在示例就在上面。
如果用「好了,不重寫的方式在非虛擬的情況下」對抗,我同意這是不好的做法,但這似乎遠遠不止這些。對我來說,語言應該:
不允許在非虛擬:: D3的使用(目前不可能的,因爲可能有其他重載F公司在把[除非在功能的情況下使用允許簽名])
或使用的完全功能和力語句
不允許轉發
或
具有實際運用覆蓋在所有情況下
或
允許功能的一些語法聲明(基本使用功能),如:
void f(*signature*) = C2::f;
究竟什麼我錯過了? 有人能想出一個方案來闡明標準中這種選擇的「原因」嗎?
供參考:所張貼的錯誤是從Visual C++ :-) – 2010-05-29 02:46:20
EDG 「sourceFile.cpp」,行24:錯誤: 對象抽象類型「D」不允許爲: 純虛函數「B1 :: f」沒有覆蓋 D d; ^ 「sourceFile.cpp」,第25行:錯誤:抽象類型的 對象 「D2」 是不允許的: 純虛函數 「B1 :: F」 不具有置換器 D2 D2; ^ – pgast 2010-05-29 02:55:52
您可能已經知道了這一點,但只是作爲參考,如果您已將f()= 0放入B1和B2的虛擬基類中,則D將起作用。看到姐妹班代表團:http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.10 – 2011-09-27 21:34:13