C++多态中的隐藏

来源:互联网 发布:网络舆情监测报告 编辑:程序博客网 时间:2024/05/14 08:36


在下面文章中有提到"林锐博士好像犯了个错误。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();/*输出为:DDD */}

 

 

原创粉丝点击