C++多态中的隐藏


在下面文章中有提到"林锐博士好像犯了个错误。C++并没有隐藏规则,林锐博士所总结的隐藏规则是他错误地理解C++多态性所致。"

C++ Virtual详解

事实上,隐藏是存在的,这里有三个类,为了容易理解,暂且叫做,爷爷类A,老爸类B,娃娃类C,在A里面定义一个虚函数,类B继承A,在B类中不重写它,而是重新定义一个同名函数,但参数不同,然后类C继承B,重写那个虚函数.之后在类B中虚函数将被隐藏,但是A和C中还是可用的.

然后,实例化C, 用B类型指针指向该实例,你会发现A中定义的虚函数无法调用,编译是通不过的,因为该函数被隐藏了,编译器无法找到它了,但是用A类型指指针来指向该实例时,该虚函数会正常调用在类C中的重写.

 

下面贴小段代码来看看C++中的继承和多态:

#include<iostream>
#include<string>
class A{
	public:
	virtual void  showname()=0;
	virtual void  setname(std::string)=0;
};
class B{
	public:
	virtual void showtype()=0;
};
class C:public B{
	public:
	virtual void showtype(){
		std::cout<<"I am Class C!"<<std::endl;
	}
	virtual void showparenttype(){
		std::cout<<"My parent is Class B!"<<std::endl;
	
	}
};
class D :public A, public C{
	protected:
	std::string _name;
	public:
	D()
	{
		_name = "none";
	}
	D(std::string name)
	{
		_name = name;
	}
	virtual void showtype()
	{
		std::cout<<"I am Class D!"<<std::endl;	
	}
	virtual void showname()
	{
		std::cout<<"I am "<<_name<<std::endl;
	}
	virtual void setname(std::string name)
	{
		_name = name;
	}
	void showparenttype(int i)
	{
		std::cout<<"My parent is Class A and C!"<<std::endl;
	}
	/*
	//这个函数若不重写将被隐藏,但隐藏限此类
	void showparenttype()
	{
		std::cout<<"@override My parent is Class A and C!"<<std::endl;
	}*/
	
};
class E: public D{
	void showparenttype()
	{	
		std::cout<<"My parent is Class D!"<<std::endl;
	}
};
int main()
{
	D* dp;
	A* ap;
	B* bp;
	C* cp;
	
	dp = new D("Harry");
	bp = dp;
	bp->showtype();
	ap = dp;
	ap->showname();
	bp = (B*)dp;
	bp->showtype();
	std::cout<<"-------------------------------"<<std::endl;
	std::cout<<"A* ap = (A*)bp;  ap->showname();"<<std::endl;
	ap = (A*)bp;
	ap->showname();
	std::cout<<"-------------------------------"<<std::endl;
	std::cout<<"A* ap = dynamic_cast<A*> (bp);  ap->showname();"<<std::endl;
	ap = dynamic_cast<A*> (bp);
	ap->showname();
	
	dp = new E();
	dp->showparenttype(1);//去掉参数将无法通过编译,因为函数己隐藏 
	cp = dp;
	cp->showparenttype();
	
}


运行结果如下图:

从这个例子中你会发现,当发生向下转换或交叉转换时,最好使用dynamic_cast,而不要有C里面的强制转换.

 

 

在C++中是多重继承的,这里就会出一些问题,当B继承了A,C也继承了A,那么当D同时继承B和C时将会发生一些问题,如果D没有重写A中定义的虚函数,那么用B指针调用时会调用B的方法,用C指针调用会调用C的方法.当然这不算什么,最让人头痛的是B和C中又同时定义了同名但不同意义的虚函数时,在D类中无法同时重写这两个函数...

下面是一个小例子,有时间可以试下

 

#include<iostream>
using namespace std;
class A
{
	public:
	virtual void show()=0;
};
class B:public A
{
	public:
	void show()
	{
		cout<<"B"<<endl;
	}
};
class C: public A
{
	public:
		void show()
	{
		cout<<"C"<<endl;
	}
};
class E 
{
	public:
	void show()
	{
		cout<<"E"<<endl;
	}
};
class D : public B, public C, public E
{
	public:
	void show()//你无法同时重写的是A和E 中的show 
	{
		cout<<"D"<<endl;
	}
};
int main()
{
	D* d = new D();
	B* b;
	C* c;
	E* e;
	c = d;
	c->show();
	b = d;
	b->show();
	e->show();
	/*
	输出为:
	D
	D
	D 
	*/
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值