1. 程式人生 > >effective c++條款33:避免遮掩繼承而來的名稱

effective c++條款33:避免遮掩繼承而來的名稱

1. using

考慮下面程式:

#include <iostream>
using namespace std;
class Based
{
public:
	void Func()
	{
		cout << "Base" << endl;
	}
	int Func(int x){}
};
class Derived : public Based
{
public:
	int Func()
	{
		cout << "Derived" << endl;
	}
};
int main()
{
	Derived D;
	D.Func(3);
	return 0;
}

我們發現該程式是無法通過編譯器的,因為編譯器查詢名稱的規則是:

首先查詢當前作用域內是否有相同的名稱,如果有,無論型別是否匹配都不再進行查詢,如果沒有再向上一級作用域查詢。

        在該例中,語句D.Func(3)會使編譯器首先查詢當前作用域也就是Derived中有沒有名稱Func,找到之後雖然函式型別不匹配但是不再向上查詢,所以無法呼叫父類中的相應的過載函式(注意:子類的作用域包含在父類的作用域之中)。

解決方案:在子類中利用using使父類中的內容子類可見:

#include <iostream>
using namespace std;
class Based
{
public:
	void Func()
	{
		cout << "Base" << endl;
	}
	int Func(int x){}
};
class Derived : public Based
{
public:
	using Based::Func;
	int Func()
	{
		cout << "Derived" << endl;
	}
};
int main()
{
	Derived D;
	D.Func(3);
	return 0;
}

這樣,我們就可以使用父類中的過載函數了。

2. 轉交函式

        在某些情況下,你可能不想繼承父類中的所有函式,當然,這不可能發生在public繼承中,因為public繼承需要滿足is-a模型,但是在private繼承中確是有意義的。 

我們不能再次使用using,因為using會使父類中所有的同名函式可見,我們需要一個轉交函式:

#include <iostream>
using namespace std;
class Based
{
public:
	void Func()
	{
		cout << "Base" << endl;
	}
	int Func(int x){}
};
class Derived : private Based
{
public:
	void Func()//轉交函式
	{
		Based::Func();
	}
};

 這樣,我們就可以選擇部分繼承而不是全部繼承。

總結:

如果你想全部繼承而且還要過載,那麼就在子類中使用using,如果你想部分繼承,那麼就在子類中使用轉交函式。