`
weihe6666
  • 浏览: 437192 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

C++ 不要重新定义继承的非虚函数

    博客分类:
  • C++
C++ 
阅读更多
不要重新定义继承的非虚函数


如果基类和派生类有相同的非虚函数,会有什么情况发生?

看下面的例子:
class B {
public:
  void mf();
};

void B::mf()
{
	cout << "Call B::mf() Function !" << endl;
}

class D: public B { ... };

int main()
{
D x;                          // x是类型D的一个对象
B *pB = &x;                   // 得到x的指针
pB->mf();                     // 通过指针调用mf

D *pD = &x;                   // 得到x的指针
pD->mf();  

return 0;
}

输出结果:
Call B::mf() Function !
Call B::mf() Function !

这两种情况调用的mf()都是B.mf(),因为类D并没有重新定义自己的mf()函数,而是继承的B的函数。

但是若D这样定义:
class D: public B {
public:
  void mf();                  // 隐藏了B::mf; 参见条款50

};

输出结果:
Call B::mf() Function !
Call D::mf() Function !
那么pB->mf(); 调用的是B::mf(),而pD->mf();调用的则是D::mf()。

行为的两面性产生的原因在于,B::mf和D::mf非虚函数是静态绑定,因为pB被声明为指向B的指针类型,通过pB调用非虚函数时将总是调用那些定义在类B中的函数 ---- 即使pB指向的是从B派生的类的对象,如上例所示。

相反,虚函数是动态绑定的,因而不会产生这类问题。如果mf是虚函数,通过pB或pD调用mf时都将导致调用D::mf,因为pB和pD实际上指向的都是类型D的对象。

mf()是虚函数的情况:
#include <iostream>
using namespace std;

class B {
public:
	virtual void mf();
};

void B::mf()
{
	cout << "Call B::mf() Function !" << endl;
}
class D: public B 
{
public :
     void mf();
};

void D::mf()
{
	cout << "Call D::mf() Function!"<< endl;
}

int main()
{
	D x;                          // x是类型D的一个对象
	B *pB = &x;                   // 得到x的指针
	pB->mf();                     // 通过指针调用mf

	D *pD = &x;                   // 得到x的指针
	pD->mf();  

	return 0;
}

输出:
Call D::mf() Function!
Call D::mf() Function!



 

分享到:
评论

相关推荐

    C++虚函数实现原理

    - 当一个类继承自另一个含有虚函数的基类时,派生类会拥有自己的虚函数表,并且该表通常会包含基类虚函数表中的函数地址,以及派生类自身定义的虚函数地址。 2. **虚表指针的初始化:** - 每个对象都会有一个虚表...

    C++虚函数表解析

    在C++编程语言中,虚函数表(Virtual Function Table,简称vtable)是实现多态性的一个关键机制。多态性允许我们使用基类指针或引用来调用派生类中的重写方法,从而提高了代码的灵活性和可扩展性。下面我们将详细...

    C++中析构函数定义成虚函数的原因.doc

    ### C++中析构函数定义成虚函数的原因 在C++编程中,为了实现多态性,虚函数机制被广泛采用。然而,在某些特定场景下,尤其是涉及到派生类和基类之间的对象管理时,将析构函数声明为虚函数显得尤为重要。本文将深入...

    C++ 虚函数表解析

    在继承层次中,派生类的虚函数表可能包含来自基类的虚函数以及自身定义的虚函数。当派生类重写(override)基类的虚函数时,虚函数表中的对应条目会被更新,指向派生类中新的函数实现。 #### 结论 虚函数表是C++中...

    继承,虚函数,抽象类

    在编程世界中,继承、虚函数和抽象类是面向对象编程(OOP)中的核心概念。这三者共同构建了类的层次结构,使得代码更加模块化,易于维护和扩展。接下来,我们将深入探讨这三个概念及其相关用法。 首先,**继承**是...

    C++结构体/函数定义转换C#函数定义/结构体

    - C++的虚函数在C#中对应为接口(Interface)或抽象类(Abstract Class)。 - C++的模板函数无法直接转换,可能需要创建多个C#方法来模拟。 4. **DLL互操作**: - 提供的文件中有`.dll`文件(如:sigimplib.dll...

    C++继承多接口,调用虚函数跳转到错误接口的虚函数的奇怪问题demo

    在“C++继承多接口,调用虚函数跳转到错误接口的虚函数的奇怪问题demo”中,我们可以假设存在以下情况: ```cpp class InterfaceA { public: virtual void foo() = 0; }; class InterfaceB { public: virtual ...

    C++中虚函数的实现机制

    2. **多态性实现**:当一个类继承自包含虚函数的基类时,子类可以重新定义(重写)该虚函数,这样就实现了运行时的多态性。 3. **虚函数表**:为了支持虚函数的动态绑定,C++编译器会在每个含有虚函数的对象中添加一...

    C++中的虚函数表图解

    在C++中,虚函数是实现多态性的重要...理解和利用虚函数表可以帮助我们更深入地理解C++的多态机制和内存布局,但在实际编程中,我们通常使用C++的语法特性,如基类指针调用虚函数,来实现多态,而非直接操作虚函数表。

    C++虚函数表测试源码

    2. 派生类定义:继承自基类,并可能重写基类的虚函数,如: ```cpp class Derived : public Base { public: void func1() override { /*...*/ } void func2() { /*...*/ } void func3() { /*...*/ } // 非虚函数 ...

    C++实验六 多态性和虚函数的应用 课程 实验报告

    在C++编程语言中,多态性和虚函数是面向对象编程的重要特性,它们允许程序员创建灵活且可扩展的代码结构。本次实验旨在深入理解和熟练运用这两个概念。实验报告的标题和描述表明,这是一个关于C++实验,特别是针对多...

    虚函数的使用技巧.rar_C++虚函数_虚函数

    虚函数调用相比非虚函数会稍慢,因为需要在运行时查找虚函数表。但在大多数情况下,这种性能差异可以忽略不计。 通过理解并熟练应用这些技巧,可以充分利用C++的多态性,编写出更加灵活和可扩展的代码。虚函数是...

    C++中虚函数工作原理和(虚)继承类的内存占用大小计算1

    每当我们定义一个含有虚函数的类,编译器会自动生成一个虚函数表,其中包含了类中所有虚函数的地址。每个对象在其内存布局中会包含一个虚指针,这个指针在对象创建时被初始化为指向相应的虚函数表。 虚函数调用的...

    C++虚函数表实现聚合(COM)

    如果类继承自其他类并重写了某个虚函数,那么子类的虚函数表将会包含新的函数指针,而父类的虚函数表仍然保留旧的函数指针。这样,当通过基类指针调用虚函数时,实际调用的是子类的版本,这就是动态绑定或多态性。 ...

    C++中的虚函数与多态

    在C++编程语言中,虚函数(Virtual Functions)和多态(Polymorphism)是面向对象编程的重要特性,它们使得程序具有高度的灵活性和可扩展性。本文将深入探讨这两个概念,结合示例代码进行详细解释。 首先,我们来...

    C++的虚函数和JAVA的抽象函数

    C++的纯虚函数则是通过在虚函数声明后加`=0`来定义的,例如`virtual void showmember() = 0;`。纯虚函数没有函数体,声明含有纯虚函数的类为抽象类,抽象类不能被实例化,只能作为其他类的基类。抽象类的目的是为了...

    C++虚函数的应用

    C++虚函数是面向对象编程中的一个重要特性,它允许我们实现多态性,即一个基类指针或引用可以调用派生类重写的成员函数。这种能力在编写可扩展和可复用的代码时非常关键。下面我们将深入探讨C++虚函数的应用及其实现...

Global site tag (gtag.js) - Google Analytics