1. 程式人生 > >C++學習筆記24,方法重寫與方法隱藏

C++學習筆記24,方法重寫與方法隱藏

轉載請註明出處:

方法重寫.是指在子類中重新編寫父類中的虛函式的實現.要求子類中的函式必須跟父類中的原型一致.

包括返回值型別(協變返回型別不算)以及引數的數目,排列順序.

#include <iostream>
#include <string>
using namespace std;
class base{
public:
	virtual	void show(int i,string s){
		cout<<i<<"+"<<s<<endl;
		cout<<"This is base show!"<<endl;
	}
};
class dirved:public base{
public:
	virtual void show(int i,string s){
		cout<<i<<"&"<<s<<endl;
		cout<<"This is dirved show!"<<endl;
	}
};

int main(){
	base b;
	b.show(10,"base");
	dirved d;
	d.show(20,"dirved");
}


通過方法的重寫,即可定義同一函式在繼承層次中的不同行為!

如果在子類中使用父類虛方法的名稱,但是引數不同,那麼這個不是重寫父類的方法,也不會過載方法,而是建立一個新方法.

#include <iostream>
#include <string>
using namespace std;
class base{
public:
	virtual	void show(int i,string s){
		cout<<i<<"+"<<s<<endl;
		cout<<"This is base show!"<<endl;
	}
};
class dirved:public base{
public:
	/*
	virtual void show(int i,string s){
		cout<<i<<"&"<<s<<endl;
		cout<<"This is dirved show!"<<endl;
	}*/
	virtual void show(){
		cout<<"This is void dirved show!"<<endl;
	}
};

int main(){
	base b;
	b.show(10,"base");
	dirved d;
	//d.show(20,"dirved");
	d.show();
}

這個時候,父類中的show()方法將被隱藏,即dirved類中無法再使用show(int,string)方法.
#include <iostream>
#include <string>
using namespace std;
class base{
public:
	virtual	void show(int i,string s){
		cout<<i<<"+"<<s<<endl;
		cout<<"This is base show!"<<endl;
	}
};
class dirved:public base{
public:
	/*
	virtual void show(int i,string s){
		cout<<i<<"&"<<s<<endl;
		cout<<"This is dirved show!"<<endl;
	}*/
	virtual void show(){
		cout<<"This is void dirved show!"<<endl;
	}
};

int main(){
	base b;
	b.show(10,"base");
	dirved d;
	d.show(20,"dirved");
	d.show();
}
編譯結果:



可以看出,對於dirved類來說,show(int,string)這個方法被隱藏起來了,即對於dirved物件來說不可見了!因此只要在子類中重新定義了父類的虛方法,父類中的所有與該方法過載的方法都將被隱藏!

這一點需要特別注意!

下面再看一些有趣的東西:

#include <iostream>
#include <string>
using namespace std;
class base{
public:
	virtual	void show(int i,string s){
		cout<<i<<"+"<<s<<endl;
		cout<<"This is base show!"<<endl;
	}
};
class dirved:public base{
public:
	virtual void show(int i,string s){
		cout<<i<<"&"<<s<<endl;
		cout<<"This is dirved show!"<<endl;
	}
};

int main(){

	dirved d;
	d.show(10,"show()");
	base &ref=d;
	ref.show(100,"ref show()");
}

子類中正確的重寫了父類中的show方法,


結果沒有疑問.但是如果你重寫子類的show方法的時候,發現應該用double代替int,於是i更改為

#include <iostream>
#include <string>
using namespace std;
class base{
public:
	virtual	void show(int i,string s){
		cout<<i<<"+"<<s<<endl;
		cout<<"This is base show!"<<endl;
	}
};
class dirved:public base{
public:
	virtual void show(double i,string s){
		cout<<i<<"&"<<s<<endl;
		cout<<"This is dirved show!"<<endl;
	}
};

int main(){

	dirved d;
	d.show(10,"show()");
	base &ref=d;
	ref.show(100,"ref show()");
}

執行結果:


看到沒有!最後那個ref.show(int,string)呼叫了base裡面的show方法!(100可以換成9.8更明顯)

明明是dirved物件的引用,怎麼就呼叫了base裡面的show方法呢?因為這實際上是建立了一個新方法!

可用override關鍵字來避免這種情況!

#include <iostream>
#include <string>
using namespace std;
class base{
public:
	virtual	void show(int i,string s){
		cout<<i<<"+"<<s<<endl;
		cout<<"This is base show!"<<endl;
	}
};
class dirved:public base{
public:
	virtual void show(double i,string s)override{
		cout<<i<<"&"<<s<<endl;
		cout<<"This is dirved show!"<<endl;
	}
};

int main(){

	dirved d;
	d.show(10,"show()");
	base &ref=d;
	ref.show(95.9,"ref show()");
}

override表示你是想要重寫base類的show方法而不是建立一個新的show方法,因此如果引數不對就會報錯!

需要注意的是,即便是重寫,只要在子類中重新定義了,父類中的相應過載函式都將會被隱藏!

如果不想既想使用父類中的show,又想重寫某一個show(),可以利用using 

#include <iostream>
#include <string>
using namespace std;
class base{
public:
	virtual	void show(int i,string s){
		cout<<i<<"+"<<s<<endl;
		cout<<"This is base show!"<<endl;
	}
	virtual void show(){
		cout<<"this is a void show"<<endl;	
	}
};
class dirved:public base{
public:
	//using 
	using base::show;
	virtual void show(int i,string s)override{
		cout<<i<<"&"<<s<<endl;
		cout<<"This is dirved show!"<<endl;
	}
};

int main(){

	dirved d;
	d.show(10,"show()");
	base &ref=d;
	ref.show(95.9,"ref show()");
	d.show();
}


這樣就兩全其美啦!