問題描述
這就是我要說的
// some guy wrote this, used as a Policy with templates
struct MyWriter {
void write(std::vector<char> const& data) {
// ...
}
};
在現有的一些代碼中,人們沒有使用模板,而是使用接口+類型擦除
In some existing code, the people did not use templates, but interfaces+type-erasure
class IWriter {
public:
virtual ~IWriter() {}
public:
virtual void write(std::vector<char> const& data) = 0;
};
其他人想要同時使用方法和寫入
Someone else wanted to be usable with both approaches and writes
class MyOwnClass: private MyWriter, public IWriter {
// other stuff
};
MyOwnClass 是根據 MyWriter 實現的.為什么MyOwnClass的繼承成員函數沒有自動實現IWriter的接口?相反,用戶必須編寫只調用基類版本的轉發函數,如
MyOwnClass is implemented-in-terms-of MyWriter. Why doesn't MyOwnClass' inherited member functions implement the interface of IWriter automatically? Instead the user has to write forwarding functions that do nothing but call the base class versions, as in
class MyOwnClass: private MyWriter, public IWriter {
public:
void write(std::vector<char> const& data) {
MyWriter::write(data);
}
};
我知道在 Java 中,當您有一個實現接口并從恰好具有合適方法的類派生的類時,該基類會自動實現派生類的接口.
I know that in Java when you have a class that implements an interface and derives from a class that happens to have suitable methods, that base class automatically implements the interface for the derived class.
為什么 C++ 不這樣做?擁有這似乎是一件很自然的事情.
Why doesn't C++ do that? It seems like a natural thing to have.
推薦答案
這是多重繼承,有兩個繼承的函數,簽名相同,都有實現.這就是 C++ 與 Java 不同的地方.
This is multiple inheritance, and there are two inherited functions with the same signature, both of which have implementation. That's where C++ is different from Java.
在靜態類型為 MyBigClass
的表達式上調用 write
因此對于需要哪個繼承函數是不明確的.
Calling write
on an expression whose static type is MyBigClass
would therefore be ambiguous as to which of the inherited functions was desired.
如果 既然問題已更改為包含純說明符,那么在派生類中實現該函數對于使類具體化和可實例化是必要的.write
僅通過基類指針調用,則不需要在派生類中定義 write
,這與問題中的聲明相反.
If Now that the question changed to include a pure specifier, implementing that function in the derived class is necessary to make the class concrete and instantiable.write
is only called through base class pointers, then defining write
in the derived class is NOT necessary, contrary to the claim in the question.
MyWriter::write
不能用于 MyBigClass
的虛調用機制,因為虛調用機制需要一個接受隱式 IWriter* const 的函數this
和 MyWriter::write
接受一個隱式的 MyWriter* const this
.需要一個新函數,必須考慮到IWriter
子對象和MyWriter
子對象的地址差異.
MyWriter::write
cannot be used for the virtual call mechanism of MyBigClass
, because the virtual call mechanism requires a function that accepts an implicit IWriter* const this
, and MyWriter::write
accepts an implicit MyWriter* const this
. A new function is required, which must take into account the address difference between the IWriter
subobject and the MyWriter
subobject.
編譯器自動創建這個新函數在理論上是可能的,但它很脆弱,因為基類的變化可能會突然導致選擇一個新函數進行轉發.它在 Java 中不那么脆弱,只有單繼承是可能的(對于要轉發到哪個函數只有一種選擇),但是在支持完全多重繼承的 C++ 中,選擇是不明確的,我們甚至還沒有開始鉆石繼承或虛擬繼承.
It would be theoretically possible for the compiler to create this new function automatically, but it would be fragile, since a change in a base class could suddenly cause a new function to be chosen for forwarding. It's less fragile in Java, where only single inheritance is possible (there's only one choice for what function to forward to), but in C++, which supports full multiple inheritance, the choice is ambiguous, and we haven't even started on diamond inheritance or virtual inheritance yet.
其實這個問題(子對象地址之間的差異)是通過虛擬繼承解決的.但它需要額外的開銷,這在大多數情況下是不必要的,而 C++ 的指導原則是不用為不使用的東西付費".
Actually, this problem (difference between subobject addresses) is solved for virtual inheritance. But it requires additional overhead that's not necessary most of the time, and a C++ guiding principle is "you don't pay for what you don't use".
這篇關于為什么 C++ 不讓基類實現派生類的繼承接口?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!