根據維基,它說[強調我的]:注意報價中的代碼片段在這里看到。
假設在基類中定義了一個純虛方法。如果派生類虛擬繼承了基類,則不需要在派生類中定義純虛方法。但是,如果派生類沒有虛擬繼承基類,則必須定義所有虛擬方法。可以在此處以互動方式探索下面的代碼。
#include <string> #include <iostream> class A { protected: std::string _msg; public: A(std::string x): _msg(x) {} void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; } virtual void pure_virtual_test() = 0; }; // since B,C inherit A virtually, the pure virtual method >pure_virtual_test doesn't need to be defined class B: virtual public A { public: B(std::string x):A("b"){} }; class C: virtual public A { public: C(std::string x):A("c"){} }; // since B,C inherit A virtually, A must be constructed in each child // however, since D does not inherit B,C virtually, the pure virtual method in A *must be defined* class D: public B,C { public: D(std::string x):A("d_a"),B("d_b"),C("d_c"){} void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; } }; // it is not necessary to redefine the pure virtual method after the parent defines it class E: public D { public: E(std::string x):A("e_a"),D("e_d"){} }; int main(int argc, char ** argv){ D d("d"); d.test(); // hello from A: d_a d.pure_virtual_test(); // pure virtual hello from: d_a E e("e"); e.test(); // hello from A: e_a e.pure_virtual_test(); // pure virtual hello from: e_a }
如何正確理解粗體字?
似乎如果派生類(即class B)沒有虛擬繼承基類,那么虛擬方法可以保留 undefined。這是我的演示代碼片段以支持我所說的:
#include <string>
#include <iostream>
class A {
protected:
std::string _msg;
public:
A(std::string x): _msg(x) {}
void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; }
virtual void pure_virtual_test() = 0;
};
// Attention: B does not inherit A ***virtually***, the pure virtual method pure_virtual_test doesn't need to be defined, either.
class B: public A { public: B(std::string x):A("b"){} };
class D: public B {
public:
D(std::string x):B("d_b"){}
void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; }
};
// it is not necessary to redefine the pure virtual method after the parent defines it
class E: public D {
public:
E(std::string x):D("e_d"){}
};
int main(int argc, char ** argv){
D d("d");
d.test();
d.pure_virtual_test();
E e("e");
e.test();
e.pure_virtual_test();
}
uj5u.com熱心網友回復:
維基百科文章中的描述是錯誤的/誤導性的。
“如果派生類沒有虛擬繼承基類,則必須定義所有虛擬方法”只有在派生類被實體化時才成立。沒有實體化的單純宣告不需要定義純虛方法。
維基百科文章聲稱“由于 D 不虛擬繼承 B、C,因此必須定義A 中的純虛擬方法”根本不正確,以下編譯沒有任何問題,沒有任何一個D或E實體化純虛擬方法:
#include <string>
#include <iostream>
class A {
protected:
std::string _msg;
public:
A(std::string x): _msg(x) {}
void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; }
virtual void pure_virtual_test() = 0;
};
// since B,C inherit A virtually, the pure virtual method pure_virtual_test doesn't need to be defined
class B: virtual public A { public: B(std::string x):A("b"){} };
class C: virtual public A { public: C(std::string x):A("c"){} };
class D: public B,C {
public:
D(std::string x):A("d_a"),B("d_b"),C("d_c"){}
};
class E: public D {
public:
E(std::string x):A("e_a"),D("e_d"){}
};
int main()
{
return 0;
}
main留空,并且D宣告E沒有問題。現在,如果您嘗試實體化其中一個,那么您將遇到問題。
uj5u.com熱心網友回復:
參考的文本似乎指的是一個名為dominance的規則,這導致了一種看起來像虛函式沒有被覆寫的情況,即使它是。這是一個例子:
struct base {
virtual void f();
};
struct i1 : base {
// doesn't override base::f
};
struct i2 : base {
void f() {} // overrides base::f
struct derived : i1, i2 {
};
使用此層次結構,您可以撰寫
derived d;
d.f(); // illegal, because ambiguous:
// i1::f, inherited from base, or i2::f
i1* p = &d;
p->f(); // calls base::f
很容易,對吧?現在讓我們從base虛擬繼承。這是主導地位開始的地方:
struct base {
virtual void f();
};
struct i1 : virtual base {
// doesn't override base::f
};
struct i2 : virtual base {
void f() {} // overrides base::f
struct derived : i1, i2 {
};
現在只有一個base子物件,并且i2::f覆寫base::f,即使在i1:
derived d;
d.f(); // calls i2::f
i1* i1p = &d;
i1p->f(); // calls i2::f
是的,呼叫i1p->f()呼叫i2的版本f,即使i1不知道任何關于i2. 只是因為i1和i2都是的基類,derived并且都具有base作為虛擬基類,所以它才有效。編譯器必須為這個跨層次呼叫獲取正確的代碼。
制作base::f純虛擬并不會改變尋找其覆寫者的規則。因此,對于非虛擬繼承,i1不會覆寫base::f,并且derived是一個抽象類。但是使用虛擬繼承,i2::f覆寫base::f,并且類derived不是抽象的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/490820.html
上一篇:如何從服務器傳輸不同的資料?
