C++继承中重定义(隐藏) 、重写(覆盖)的区别

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++中继承中重载、重写、重定义的区别

总结:
重定义与向上造型和向下造型无关
指针类型是什么类型就调用相应类型的成员函数
而重写一般是根据基类的引用(指针)指向的对象来确定自己具体该调用哪一个类的虚函数,这里涉及到虚函数表的概念,有兴趣的同学可以了解下虚函数表的概念。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值