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