虚继承
#include
using namespace std;
class Parent
{
public:
void func(int i){ cout << "Parent::func(int i)" << endl; }
virtual void func2() { cout << "Parent::func2()" << endl; }
virtual void func2(int i) { cout << "Parent::func2(int i)" << endl; }
void func3(){ cout << "Parent::func3()" << endl; }
virtual void func4(){ cout << "virtual Parent::func4()" << endl; }
virtual void func5(int i){ cout << " virtual Parent::func5(int i)" << endl; }
};
class Child : public Parent
{
public:
void func(){ cout << "Child::func()" << endl; }
void func2(){ cout << "Child::func2()" << endl; }
void func2(int i){ cout << "Child::func2(int i)" << endl; }
void func5( ){ cout << "Child::func5()" << endl; }
};
int main()
{
Parent *pp = new Child();
pp->func(1); //Parent::func(int)
pp->func2(1); //Child::func2(int i) ---覆盖
//pp->func(); //编译错误 pp是父类指针,无法用调用子类
pp->func2();//Child::func2()
pp->func(1);//隐藏-转父类指针可以调用,但是子类指针不能调用
pp->func5(1);//隐藏-转父类指针可以调用,但是子类指针不能调用
delete pp;
Child *pc = new Child();
//pc->func(1);//隐藏,编译错误:如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字,基类的函数将被隐藏
//pc->func5(1);//隐藏,编译错误:同上。(不论有无virtual关键字,基类的函数将被隐藏
pc->func2(1); //Child::func2(int i)
pc->func(); //Child::func()
pc->func2(); //Child::func2()
pc->func3(); //Parent::func3(),子类直接继承父类的普通函数
pc->func4();// virtual Parent::func4(),子类没有隐藏父类的虚函数
delete pc;
}
如果不是虚函数,就直接根据指针类型(父类指针、子类指针,)来确定调用子类还是父类的方法,与实际指针指向的对象是父类还是子类无关。
如果是虚函数,就调用实际指向内存对象的方法,不论指针类型
c++重载、覆盖、隐藏的区别和执行方式:
转自:http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/05/2537451.html
既然说到了继承的问题,那么不妨讨论一下经常提到的重载,覆盖和隐藏
4.1成员函数被重载的特征
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
4.2“覆盖”是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
4.3“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,特征是:
(1)如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,但是参数相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
小结:说白了就是如果派生类和基类的函数名和参数都相同且
用了virtual
,属于覆盖,这是可以理解的吧,完全一样当然要覆盖了;
如果只是函数名相同,参数并不相同,则属于隐藏
。覆盖就只有一种情况:
派生类和基类的函数名和参数都相同且
用了virtual
4.4 三种情况怎么执行:
4.4.1 重载:看参数。
4.4.2 隐藏:用什么就调用什么。转成父类类型的指针就用父类的方法,转成子类类型的指针就用子类的方法,子类隐藏了父类的函数,子类指针就无法调用父类的方法了,直接编译错误
4.4.3 覆盖:调用派生类。