C++构造函数中调用虚函数

谈谈关于构造函数中调用虚函数的情况,仅讨论单继承,不考虑虚拟继承和多重继承。

测试平台:VS2013 + Win7X64

一个例子:

#include <stdlib.h>
#include <stdio.h>

class Base
{
private:
    int __data;

public:
    Base()
    {
        this->Func();
    }

public:
    virtual void Func()
    {
        printf("Base::Func");
    }
};

class Deri : public Base
{
public:
    Deri()
    {
        this->Func();
    }

public:
    virtual void Func()
    {
        printf("Deri::Func\n");
    }

};

int main(int argc, char** argv)
{
    Deri d;

    getchar();
    return 0;
}

输出:

Base::Func

Deri::Func


首先讨论下对象d的构造情况。

1 先构造基类部分,调用基类Base的构造函数,这个时候,派生类部分还没有产生,这时候虚表应该是绑定基类的,自然调用的是Base::Func()

2 再构造派生类部分,这个时候,虚表发生变化,绑定在派生类上,调用Deri::Func()

虽然,在派生类中有重载Func这个函数,但是,在构造基类部分的时候,派生类的成员数据还没有初始化,如果是调用派生类中的Func,会造成错误,内存越界甚至崩溃。


在函数中,可以通过打印虚表地址:

-- Base::Func()

int* vtl = (int*)*((int*)this);

std::cout << "Base: " << this << "  VTable: " << vtl << std::endl;

-- Deri::Func()

int* vtl = (int*)*((int*)this);

std::cout << "Deri: " << this << "  VTable: " << vtl << std::endl;

输出:

Base: 0028F980  VTable: 003FDC78
Deri: 0028F980  VTable: 003FDC98

发现,虚表的地址是不断变化的。

时间: 2024-08-02 11:50:29

C++构造函数中调用虚函数的相关文章

c++ 构造函数中调用虚函数的实现方法_C 语言

我们知道:C++中的多态使得可以根据对象的真实类型(动态类型)调用不同的虚函数.这种调用都是对象已经构建完成的情况.那如果在构造函数中调用虚函数,会怎么样呢? 有这么一段代码: class A { public: A ():m_iVal(0){test();} virtual void func() { std::cout<<m_iVal<<' ';} void test(){func();} public: int m_iVal; }; class B : public A {

《Effective C++》读书笔记09:绝不在构造和析构过程中调用virtual函数

首先明确一下,对于一个继承体系,构造函数是从基类开始调用了,而析构函数则正 好相反,从最外层的类开始. 对于在构造函数中调用virtual函数,先举个例子: 1 class Transaction //所有交易的基类 2 { 3 public: 4 Transaction(); 5 virtual void logTransaction() const = 0;//日志记 录,因交易类型的不同而有不同的记录 6 } 7 8 Transaction::Transaction()//构造函数实现 9

C++中的虚函数和动态联编

  面向对象程序设计的基本观点是用程式来仿真大千世界,这使得它的各种根本特性非常人性化,如封装.继承.多态等等,而虚函数就是c++中实现多态性的主将.为了实现多态性,c++编译器也革命性地提供了动态联编(或叫晚捆绑)这一特征. 虚拟函数亦是mfc编程的关键所在,mfc编程主要有两种方法:一是响应各种消息,进行对应的消息处理.二就是重载并改写虚拟函数,来实现自己的某些要求或改变系统的某些默认处理. 虚函数的地位是如此的重要,对它进行穷根究底,力求能知其然并知其所以然 对我们编程能力的提高大有好处.

详解C++编程中的虚函数_C 语言

我们知道,在同一类中是不能定义两个名字相同.参数个数和类型都相同的函数的,否则就是"重复定义".但是在类的继承层次结构中,在不同的层次中可以出现名字相同.参数个数和类型都相同而功能不同的函数. 人们提出这样的设想,能否用同一个调用形式,既能调用派生类又能调用基类的同名函数.在程序中不是通过不同的对象名去调用不同派生层次中的同名函数,而是通过指针调用它们.例如,用同一个语句"pt->display( );"可以调用不同派生层次中的display函数,只需在调用前

C++中的虚函数

虽然很难找到一本不讨论多态性的C++书籍或杂志,但是,大多数这类讨论使多态性和C++虚函数的使用看起来很难.我打算在这篇文章中通过从几个方面和结合一些例子使读者理解在C++中的虚函数实现技术.说明一点,写这篇文章只是想和大家交流学习经验因为本人学识浅薄,难免有一些错误和不足,希望大家批评和指正,在此深表感谢! 一.基本概念 首先,C++通过虚函数实现多态."无论发送消息的对象属于什么类,它们均发送具有同一形式的消息,对消息的处理方式可能随接手消息的对象而变"的处理方式被称为多态性.&q

.NET中的虚函数

面向对象的程序设计有三大要素,封装.继承和多态.虚函数是多态的重要组成部分,同时又在类的继承关系中有着很多变化.本文讨论.NET中对虚函数的支持. 首先,我们通过一个例子来看看虚函数的普通用法: class CA { public virtual void Foo() { Console.WriteLine("CA.Foo"); } } class CB : CA { public override void Foo() { Console.WriteLine("CB.Foo

浅析C++中的虚函数_C 语言

一.定义定义:在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数. 语法:virtual 函数返回类型函数名(参数表) { 函数体 } 用途:实现多态性,通过指向派生类的基类指针,访问派生类中同名覆盖成员函数 虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public. 定义为virtual的函数是基类期待派生类重新定义的,基类希望派生类继承的函数不能定义为虚函数. 二.作用虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函

简单解读C++中的虚函数_C 语言

虚函数 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离:用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略.下面来看一段简单的代码 class A{ public: void print(){ cout<<"This is A"<<endl;} }; class B:public A{ public: void print()

深入解析C++中的虚函数与多态_C 语言

1.C++中的虚函数C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Tab