C++ 隐藏

文章讲述了C++中派生类如何隐藏基类的同名函数,无论函数是否有virtual修饰。这种情况不是覆盖也不是重载,而是名称隐藏。C++的名称查找规则导致基类的函数被派生类的同名函数遮掩。通过using声明可以显式地使基类的函数在派生类作用域内可见,从而避免隐藏问题。文章提供了两个示例来说明两种隐藏情况,并给出了如何实现继承重载的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

隐藏一定是用大对象指针/引用(派生类)

一.隐藏的两类情况:

1.派生类中声明了一个与基类同名的函数但参数却不同,不管基类有无virtual

2.派生类中声明了一个与基类同型的函数,但基类该函数未修饰为virtual函数

(同型函数:同名同参

注意:情况1不是覆盖,无virtual为静态编译

          情况2不是重载,重载发生在同一个名字空间

两类情况的结果:会发生 子类隐藏父类只能访问子类的该函数

二、WHY?

这涉及:名称的隐藏 与作用域有关

C++名称查找规则:先去local作用域内查找,如果找到就不再查找其他作用域

(1)例:情况1

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();
};

20210511154007630.png

由于以作用域为基础的"名称查找规则",因此基类所有名为mf1和mf3的函数都被派生类的mf1和mf3函数都遮掩掉了。从名称查找的观点来看:Base::mf1()和Base::mf3不再被派生类继承:

Derived d;
int x;
d.mf1();  // ok, 调用Derived::mf1;
d.mf1(x);  // error,因为Derived::mf1遮掩了Base::mf1
d.mf2();  // ok,调用Base::mf2
d.mf3();  // ok, 调用Derived::mf3
d.mf3(x);  // error,因为Derived::mf3遮掩了Base::mf3

这可以看出,即使基类和派生类的函数有不同的参数类型不管函数是virtual还是non-virtual,都有名称隐藏问题

这些行为背后的基本理由是为了防止你在程序库或者应用框架内建立新的派生类时附带的从疏远的基类继承重载函数。

如何实现继承重载?

实际上如果你正在使用public继承而又不继承那些重载函数,就会违反基类和派生类的is-a关系,因此你会想要推翻C++对”继承而来的名称“的缺省隐藏问题。

你可以使用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::mf3; // 让基类的mf1和mf3内的所有东西在派生类的作用于可见
	virtual void mf1();
	void mf3();
	void mf4();
};

 现在,继承机制恢复了:

Derived d;
int x;
d.mf1();  // ok, 调用Derived::mf1;
d.mf1(x);  // ok, 调用Base::mf1
d.mf2();  // ok,调用Base::mf2
d.mf3();  // ok, 调用Derived::mf3
d.mf3(x);  //ok, 调用Base::mf3

(2)例:情况2

#include <iostream>
using namespace std;
//隐藏第一种情况
class Base
{
public:
	void f() //基类非virtual
	{
		cout << "基类f()" << endl;
	}
};

class Derived : public Base
{
public:
	void f()//派生类有一个同型函数f()
	{
		cout << "派生类f()" << endl;
	}
};
int main()
{
	Base* p = new Derived();
	Derived* q = (Derived*)p;
	q->f(); //输出:派生类f()
	//调用Derived::f() 用派生类q指针访问,下隐藏上,Derived::f()隐藏Base::f()
}

参考:(2条消息) C/C++编程:避免隐藏继承而来的名称_OceanStar的学习笔记的博客-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值