Effective C++ (E3 33)笔记之名称遮掩规则及其应对手法

C++中名称遮掩规则即为:遮掩名称。这个遮掩的名称和类型无关。
编译器按照从最内部作用域向外逐个查找,直到找到匹配的名称为止。

Base类:

#include<iostream>
using namespace std;

class Base{
private:
	int x;
public:
	virtual void mf1()=0;
	virtual void mf1(int){
		cout<<"Base::mf1(int)"<<endl;
	}
	virtual void mf1(int,int){
		cout<<"Base::mf1(int,int)"<<endl;
	}
	virtual void mf2(){
		cout<<"Base::mf2()"<<endl;
	}
	void mf3(){
		cout<<"Base::mf3()"<<endl;
	}
	void mf3(double){
		cout<<"Base::mf3(double)"<<endl;
	}
};

void Base::mf1(){
	cout<<"Base::mf1()"<<endl;
}

Derived0类:

class Derived0:public Base{
public:
	virtual void mf1(){
		cout<<"Derived0::mf1()"<<endl;
	}
	void mf3(){
		cout<<"Derived0::mf3()"<<endl;
	}
	void mf4(){
		cout<<"Derived0::mf4()"<<endl;
	}
};

通过Derived0对象试验:

	int x=1;
	Derived0 dv0;
	dv0.mf1();	//ok, derived0::mf1()
	//dv0.mf1(x);	//err, base::mf1(int) is hided by derived0::mf1()
	dv0.mf2();	//ok, base::mf2()
	dv0.mf3();	//ok, derived0::mf3()
	//dv0.mf3(x);	//err,base::mf3(double) is hided by derived0::mf3()
	dv0.mf4();	//ok, derived0::mf4()

如注释所言,基类中带参的mf1、mf3被派生类中不带参的 mf1、mf3名称遮掩了而导致编译器找不到此函数。即便函数签名不同。
而作为public继承,继承基类中的重载函数再正当不过,有2种手段来避免上述的名称遮掩现象:

方法一 、使用using声明式

以下是同样继承自Base类的Derived1类:

class Derived1:public Base{
public:
	using Base::mf1;
	using Base::mf3;
	virtual void mf1(){
		cout<<"Derived1::mf1()"<<endl;
	}
	void mf3(){
		cout<<"Derived1::mf3()"<<endl;
	}
	void mf4(){
		cout<<"Derived1::mf4()"<<endl;
	}
};

通过Derived1对象试验:

	Derived1 dv1;
	dv1.mf1();	//ok,derived1::mf1()
	dv1.mf1(x);	//ok, base::mf1(int)
	dv1.mf2();	//ok, base::mf2()
	dv1.mf3();	//ok, derived::mf3()
	dv1.mf3(x);	//ok, base::mf3(double)
	dv1.mf4();	//ok, derived::mf4()

现在没有问题了。

但使用了using声明后,继承类只能全盘接收基类中所有叫mf1、mf3的函数。有没有部分接收的方法?

方法二 、使用转交函数

以下是同样继承自Base类的Derived2类:

class Derived2:public Base{
public:
	virtual void mf1(){
		Base::mf1();
	}
	virtual void mf1(int x){
		Base::mf1(x);
	}
	void mf3(){
		Base::mf3();
	}
	//int mf3(){	//mf3()'s signature is the same so it cannot be overloaded
	//	cout<<"Derived1::mf3()"<<endl;
	//	return 0;
	//}	
};

通过Derived2对象试验:

	Derived2 dv2;
	dv2.mf1();	//ok, base::mf1()
	dv2.mf1(x);	//ok, base::mf1(int)
	//dv2.mf1(x,x);	//err, base::mf1(int,int) is hided by others
	dv2.mf3();	//ok, base::mf3()
	//dv2.mf3(x);	//err, base::mf3(double) is hided by derived2::mf3()

可以看到,派生类中的mf1()、mf1(x)、mf3()作为转交函数,使用“基类::函数”的形式明确在派生类中,究竟哪些基类函数名称不能被遮掩,需要被派生类继承下来。由于base::mf1(int,int)没有被指定,还是被其他同名mf1遮掩了。

另外在Base类中,mf1作为纯虚函数没有定义,而派生类中的mf1()转交函数需要基类的定义。因此 可以为纯虚函数提供一份定义



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值