當初學C++繼承的時候,一開始確實被裏面亂七八糟的關係弄的暈得不輕。單繼承、多繼承、虛繼承.....Ծ‸Ծ
當時好像聽過一句話:“等你學Java的時候就好了,Java把這些東西都扔了” 罒ω罒//偷笑.jpg
爲什麼會丟棄這些東西嘞?往下看:
#include<iostream> //錯誤代碼
using namespace std;
class A{
public:
int a=1;
void ex(){
cout<<"This is A"<<endl;
}
};
class B:public A{
public:
void f(){
cout<<"This is B"<<endl;
}
};
class C:public A{
public:
void f(){
cout<<"This is C"<<endl;
}
};
class D:public B,public C{
void ee(){
cout<<"this is D"<<endl;
}
};
int main(){
D d;
cout<<d.a<<endl;
// d.B::f();
cin.get();
return 0;
}
這是一個關於多重繼承的小例子,如圖:
這裏編譯時會顯示出錯:
出錯原因是因爲,系統不知道這個a,是D去繼承,B繼承A而來的還是C繼承A而來的(二義性)。因爲D通過繼承B、C帶來了兩個
A的副本。這裏可以通過改寫成:
int main(){
D d;
cout<<d.B::a<<endl; //指定這是訪問d繼承B從A繼承來的a
return 0;
}
來更正(很雞肋對吧)
當然,也可以用虛繼承去解決這個問題(讓D裏面只保留一個A的副本)(B、C繼承A時加上virtual,聲明這是虛繼承):
#include<iostream>
using namespace std;
class A{
public:
int a=1;
void ex(){
cout<<"This is A"<<endl;
}
};
class B:virtual public A{
public:
void f(){
cout<<"This is B"<<endl;
}
};
class C:virtual public A{
public:
void f(){
cout<<"This is C"<<endl;
}
};
class D:public B,public C{
void ee(){
cout<<"this is D"<<endl;
}
};
int main(){
D d;
cout<<d.a<<endl;
// d.B::f();
cin.get();
return 0;
}
以上就是多繼承中的菱形繼承問題,用virtual解決之後就完了?沒辣麼簡單。
如果B和C中都有一個函數f( ),直接寫d.f()還是會報錯,因爲機子又不知道這個f()哪來的了((~ ̄(OO) ̄)ブ)
還是二義性問題:
還是一樣,改寫main函數,可以更正過來:
int main(){
D d;
d.B::f(); //指定這是d調用B的f()
return 0;
}
總結:多繼承的實用性不強,並且多繼承中錯綜複雜的關係降低了程序的容錯率。
這也許就是Java將其拋棄之的原因吧(罒ω罒)
另一方面,Java也提出了Interface(接口)的概念,藉以彌補多繼承的功能。