C++继承中重定义(隐藏) 、重写(覆盖)的区别
重写
概念:重写(覆盖):是指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
class BaseClass
{
public:
BaseClass()
{
std::cout << "BaseClass ()" << std::endl;
}
~BaseClass()
{
std::cout << "~BaseClass ()" << std::endl;
}
public:
virtual void AddFunc(int a,int b)
{
std::cout << "BaseClass::AddFunc()" << std::endl;
}
};
class DerivedClassA:public BaseClass
{
public:
DerivedClassA()
{
std::cout << "DerivedClassA ()" << std::endl;
}
~DerivedClassA()
{
std::cout << "~DerivedClassA ()" << std::endl;
}
public:
void AddFunc(int a,int b)
{
std::cout <<"DerivedClassA::AddFunc() " << std::endl;
}
};
代码中定义了两个类,其中DerivedClassA类派生自BaseClass,并且DerivedClassA类重写了AddFunc方法。
执行下面的语句看下结果。
BaseClass *baseClassPtr;
DerivedClassA * derivedClassAPtr = new DerivedClassA();
baseClassPtr = derivedClassAPtr;
baseClassPtr->AddFunc(2,3);
结果:
baseClassPtr是基类的指针,但是调用的是子类DerivedClassA的AddFunc方法。
BaseClass *baseClassPtr;
DerivedClassA * derivedClassAPtr = new DerivedClassA();
baseClassPtr = derivedClassAPtr;
这种方式被称为向上造型
还有另外一种方式被称为向下造型
BaseClass * baseClassPtr = new BaseClass();
DerivedClassA *derivedClassAPtr;
derivedClassAPtr =(DerivedClassA *) baseClassPtr;
derivedClassAPtr->AddFunc(2,3);
结果
DerivedClassA 是派生类指针,但是调用的是父类BaseClass 的AddFunc方法。
注:
向上造型是安全的,向下造型是不安全的。
重定义
【重定义是指派生类的函数屏蔽了与其同名的基类函数,注意只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。】
class BaseClass
{
public:
BaseClass()
{
std::cout << "BaseClass ()" << std::endl;
}
~BaseClass()
{
std::cout << "~BaseClass ()" << std::endl;
}
public:
void AddFunc(int a,int b)
{
std::cout << "BaseClass::AddFunc()" << std::endl;
}
};
class DerivedClassA:public BaseClass
{
public:
DerivedClassA()
{
std::cout << "DerivedClassA ()" << std::endl;
}
~DerivedClassA()
{
std::cout << "~DerivedClassA ()" << std::endl;
}
public:
void AddFunc(int a, int b)
{
std::cout <<"DerivedClassA::AddFunc() " << std::endl;
}
};
同样的代码,只不过我们去掉了基类AddFunc中的vitural关键字。
当我们采用相同的代码运行时,结果会是什么样的
向上造型:
BaseClass *baseClassPtr;
DerivedClassA * derivedClassAPtr = new DerivedClassA();
baseClassPtr = derivedClassAPtr;
baseClassPtr->AddFunc(2,3)
结果:
对比重写中的向上造型写法,baseClassPtr->AddFunc调用的不再是子类DerivedClassA
的AddFunc方法,而是父类BaseClass 自己的AddFunc方法。
向下造型:
BaseClass * baseClassPtr = new BaseClass();
DerivedClassA *derivedClassAPtr;
derivedClassAPtr =(DerivedClassA *) baseClassPtr;
derivedClassAPtr->AddFunc(2,3);
对比重写中的向下造型写法,derivedClassAPtr->AddFun调用的不再是父类BaseClass 中的AddFunc
方法,而是子类DerivedClassA自己的方法。
参考文档:
C++中继承中重载、重写、重定义的区别
总结:
重定义与向上造型和向下造型无关
指针类型是什么类型就调用相应类型的成员函数
而重写一般是根据基类的引用(指针)指向的对象来确定自己具体该调用哪一个类的虚函数,这里涉及到虚函数表的概念,有兴趣的同学可以了解下虚函数表的概念。