Effective C++ Item33:避免遮掩继承而来的名称

这个主题和继承关系不大,主要是对作用域的理解和把握

还是通过代码来看:

class Base {
private:
	int x;
public:
	virtual void mf1() = 0;
	virtual void mf1(int);
	virtual void mf2();
	void mf3();
	void mf3(double);
};
class Derived : public Base {
public:
	virtual void mf1();
	void mf3();
	void mf4();
};
int main()
{
	Derived d;
	int x = 1;
	d.mf1();//没问题,调用Derived::mf1()
	d.mf1(x);//错误,Derived::mf1()遮掩了Base::mf1函数
	d.mf2();//没问题,调用Derived::mf2()
	d.mf3();//没问题,调用Derived::mf3()
	d.mf3(x);//错误,Derived::mf1()遮掩了Base::mf3函数
	return 0;
}

上述代码中,子类中的mf1和mf3遮掩了基类中的所有名为mf1和mf3的函数,于是,Base::mf1和Base::mf3就不再被Derived继承。

这样做的好处在于避免在程序库或应用框架内建立新的子类时,附带地从疏远的基类继承重载函数。像例子中,避免了基类中mf1和mf3函数的重载函数的继承。

而pubic继承,子类与基类是“is-a”的关系,意味着子类拥有基类的所有东西,如果使用public继承,又不继承基类中的重载函数,那就违反了public继承的意义

为了实现public继承中子类与基类的“is-a”的关系,有两种方案:

1. 方案一:使用using声明式实现:

class Base {
private:
	int x;
public:
	virtual void mf1() = 0;
	virtual void mf1(int);
	virtual void mf2();
	void mf3();
	void mf3(double);
};
class Derived : public Base {
public:
	using Base::mf1; //使用using声明式使Base::mf1在子类中可见
	using Base::mf3; //使用using声明式使Base::mf3在子类中可见
	virtual void mf1();
	void mf3();
	void mf4();
};
int main()
{
	Derived d;
	int x = 1;
	d.mf1();//没问题,调用Derived::mf1()
	d.mf1(x);//没问题,调用Base::mf1函数
	d.mf2();//没问题,调用Derived::mf2()
	d.mf3();//没问题,调用Derived::mf3()
	d.mf3(x);//没问题,调用Base::mf3函数
	return 0;
}

方案一解决了由于在子类中重新定义函数,遮掩了基类重载函数的问题。using声明式使得基类中的函数在子类作用域中都可见。但是,我们可能并不总是希望继承基类所有的函数都在子类可见,这样的需求该如何满足?

2. 方案二使用private继承,并在继承中使用了转交函数(forwarding function)来解决上述的问题:

class Base {
private:
	int x;
public:
	virtual void mf1() = 0;
	virtual void mf1(int);
};
class Derived : private Base {
public:
	virtual void mf1() {
		Base::mf1();//转交函数,仅继承基类无参的mf1函数
	}
};
int main()
{
	Derived d;
	int x = 1;
	d.mf1();//没问题,调用Derived::mf1()
	d.mf1(x);//错误,Base::mf1函数被遮掩
	return 0;
}

在子类的mf1函数,将mf1函数需要执行的任务交给了Base类的mf1函数来执行。

而在其中仅调用了Base的mf1函数的无参函数,达到了遮掩mf1有参函数的目标。

3. 总结:

  1. 名称遮掩的问题本质是对作用域的理解,能够很好理解作用域,名称遮掩的问题也不是难事。
  2. 解决名称遮掩问题的方式有using声明式和转交函数方法,可根据实际应用场景选择合适的方案。
  3. 有关转交函数的问题可查阅《Exceptional C++》的条款46,有对转交函数的详细介绍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值