避免在派生类中重新定义基类的非虚函数

我们都知道,在基类中定义虚函数的目的是允许派生类拥有相同接口却可以有不同的实现,通过对象的指针或引用来访问虚函数可以实现运行时的多态。这么说来,在派生类中重定义(override)虚函数是没有任何问题的。那么,可以重定义基类中的非虚函数吗?

答案是:技术上你可以这样做(至少编译器不会报错),但是绝大多数情况下不应该做。

class Base
{
public:
   void f() { cout << "Base::f()" << endl; }
};

class Derived: public Base
{
public:
   void f() { cout << "Derived::f()" << endl; }
};

int main()
{
   Derived d;
   Base *pb = &d;
   // Base::f()
   pb->f();
   Derived *pd = &d;
   // Derived::f()
   pd->f();   
}

上面的代码有一个诡异的行为:对同一个派生类对象调用同样的函数,返回的结果是不一样的。这是因为普通的非虚函数体在编译期就与函数调用绑定,指针的类型决定了哪个函数被调用。通过Base调用的f一定是基类的,而通过Derived调用的f一定是派生类的。
从面向对象的角度来说,在派生类中重定义基类中的非虚函数可能会违反公有继承Is-A的关系。公有继承是说每一个派生类对象都可以被当做基类对象来处理。基类的每一个接口和不变量派生类也有。而非虚函数的具体实现是类不变量的一部分。如果重定义了非虚函数,类不变量就可能被打破,派生类对象将不再是基类对象(当通过指向派生类对象的指针访问f时)。

很少情况下,需要重定义非虚函数。一个特例是为了解决私有继承中的名字隐藏问题。在私有继承中,基类的公有函数在派生类中都是私有,如果派生类想要继承基类的某个接口,可以使用所谓的forwarding function。即通过定义一个与基类一模一样的函数,它的实现仅仅是调用基类的对应函数。注意,使用using语句是不可行的,它会把同名的所有重载函数(f()与f(int))都一起导入派生类,参见:C++名字隐藏对公有继承的影响

class Base
{
public:
  f();
  f(int i);
};

class Derived: private Base
{
public:
  // forwarding function
  f() { Base::f(); }
};

小结:
绝大多数情况下不要重新定义基类的非虚函数,那样会打破公有继承Is-A的关系,而且行为诡异。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基类虚函数是面向对象编程两个不同的概念,它们在实现多态性时起到关键作用。 **虚函数(Virtual Function)**: 虚函数是在基类声明为虚的成员函数,当从派生类的对象上调用该函数时,会自动关联到实际的对象类型(即动态绑定),而不是基类。这样可以确保使用子类的行为,即使在基类指针或引用上调用。虚函数定义通常在基类使用`virtual`关键字。 **虚基类(Virtual Base Class)**: 虚基类是一个特殊的基类,当一个派生类继承自虚基类时,所有从虚基类继承的成员都将成为该派生类的一部分,但每个派生类只有一份拷贝。这样可以避免产生多次的间接继承,减少内存浪费,并简化继承关系。声明虚基类使用`virtual`关键字放在继承列表的最前面。 总结一下区别: 1. **目标不同**:虚函数的目标在于实现运行时的多态,使基于基类的指针/引用能正确调用相应子类的行为;虚基类则是为了解决多个层次继承复和复杂性问题。 2. **应用场合**:虚函数主要在需要动态行为的继承场景使用;虚基类则在有深层次嵌套继承且需要简化结构时考虑。 3. **语法不同**:虚函数是成员函数级别的声明;虚基类是类级别的声明,并影响整个继承链。 相关问题: 1. 虚函数如何实现动态绑定? 2. 虚基类如何解决多继承的问题? 3. 如何在类声明指定一个基类为虚基类

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值