文档章节

C++中初始化的顺序问题

zhangyujsj
 zhangyujsj
发布于 2016/04/02 15:21
字数 634
阅读 49
收藏 4

C++的初始化顺序非常重要,牢记才能不出常识性的错误。

其初始化顺序为:

1 类中的static成员是最先初始化的,这个是先于main函数的执行的,但是必须注意,如果这个成员只是在类中声明,而没有在类外边进行定义的话,那么这个是不会开辟内存的,是不会初始化的。

2 调用基类的构造函数。但是基类分为两种顺序,特别注意。一种是虚继承的基类;另一种是普通继承的虚基类和普通基类。

虚继承的基类的构造函数是最先调用的,接着虚基类和普通基类的构造函数是按顺序执行的(按照继承的顺序,而不是在类的构造函数中的初始化顺序)。

3 类的数据成员进行初始化,如果是类类型的数据成员就会调用相应的默认构造函数。注意这个顺序是根据类中数据成员定义出现的顺序进行初始化的。

4 最后是进入类自己的构造函数的代码执行

如下的测试代码:

#include <iostream>  
#include <string>  
using namespace std;

//抽象类A  
class A
{
public:
    A()
    {
        cout << "抽象类A的构造函数" << endl;
    }
    //纯虚函数fun  
    virtual void fun1() = 0;
};

//抽象类B  
class B
{
public:
    B()
    {
        cout << "抽象类B的构造函数" << endl;
    }
    //纯虚函数fun  
    virtual void fun2() = 0;
};

//普通类C  
class C
{
public:
    C()
    {
        cout << "类C的构造函数" << " 用于虚继承的" << endl;
    }
};

//普通类D  
class D
{
public:
    D()
    {
        cout << "类D的构造函数" << " 用于虚继承的" << endl;
    }
};

//普通类C  
class E
{
public:
    E()
    {
        cout << "类E的构造函数" << endl;
    }
};

//普通类D  
class F
{
public:
    F()
    {
        cout << "类F的构造函数" << endl;
    }
};

//普通类D  
class G
{
public:
    G()
    {
        cout << "类G的构造函数" << endl;
    }
};

//普通类D  
class H
{
public:
    H()
    {
        cout << "类H的构造函数" << endl;
    }
};
//普通类D  
class M
{
public:
    M()
    {
        cout << "类M的构造函数" << endl;
    }
};

class Test : public E, public A, public F, public B, virtual public C, virtual public D
{
public:
    Test() :B(), A(), D(), C(), F(), E()
    {
        cout << "类Test的构造函数" << endl;
    }
    void fun1()
    {
    }
    void fun2()
    {
    }
private:
    G g; // 会自动调用这个数据成员的构造函数
    static H h;
    static M m;
};

H Test::h; // 注意这个定义,非常重要,这就是static类型的成员变量的实现方式

int main(int argc, char* argv[])
{
    cout << "main begin" << endl;
    Test test;
    cout << "main end" << endl;
    return EXIT_SUCCESS;
}


这个程序的运行结果如下:



© 著作权归作者所有

zhangyujsj
粉丝 24
博文 358
码字总数 224241
作品 0
广州
私信 提问
Java 走向C++

本文不涉及一些微妙蛋疼的语法比较, 关注的是宏观方面, 当然后期逐步更新如果, 如果觉得必要, 可能会加上. 议题之一: 初始化的比较 1. CPP基类的任何类构造函数会默认调用父类的不带参数的构...

晨曦之光
2012/03/09
61
0
Java 走向C++

本文不涉及一些微妙蛋疼的语法比较, 关注的是宏观方面, 当然后期逐步更新如果, 如果觉得必要, 可能会加上. 议题之一: 初始化的比较 1. CPP基类的任何类构造函数会默认调用父类的不带参数的构...

晨曦之光
2012/03/09
93
0
在main函数之前调用函数,以及对设计的作用

前几天为新员工写一个简单的测试框架,可让他们方便的写测试用例并且执行。期间遇到一个问题就是如何让他们增加测试用例而用不影响测试框架的代码?c++的单件模式可以解决这个问题,但是其中...

晨曦之光
2012/06/06
89
0
C++ 对象资源管理惯用法

原文:C++ 对象资源管理惯用法 作者:Breaker 关于 C++ 对象资源管理的惯用法,note-to-self + keynote + idiom case + cross-reference 式笔记 keyword: RAII, deleter, Two-stage Initiali...

晨曦之光
2012/05/23
182
0
[C++再学习系列] 全局或静态变量(对象)的初始化

  对于C语言的全局和静态变量,不管是否被初始化,其内存空间都是全局的;如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化。由于内置变量无须资源释放操作,仅需要回收内...

技术小美
2017/11/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

视频如何加水印?

很多视频制作者的视频都被他人盗用过,为了防止自己的劳动成果被他人窃取,给视频加水印对于视频制作者来说,是一件非常重要的事情。那么下面分享一个手机给视频加水印的方法,一起来看看吧!...

白米稀饭2019
28分钟前
5
0
004-Envelop-基于Blockstack的文件传输dapp

本篇文章主要介绍基于Blockstack的文件传输工具; ####A-链接地址 官网地址:https://envelop.app/ Github地址:https://github.com/envelop-app ####B-特性: 1: Share private files easil...

Riverzhou
31分钟前
7
0
SpringCloud——声明式调用Feign

Feign声明式调用 一、Feign简介 使用Ribbon和RestTemplate消费服务的时候,有一个最麻烦的点在于,每次都要拼接URL,组织参数,所以有了Feign声明式调用,Feign的首要目标是将Java HTTP客户端...

devils_os
36分钟前
7
0
《JAVA核心知识》学习笔记 (22. 数据结构)

22.1.1. 栈(stack) 栈( stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶 (top)。它是后进先出(LIFO)的。对栈的基本操作只有 push(进栈)和 pop(出栈...

Shingfi
42分钟前
6
0
你对AJAX认知有多少(1)?

AJAX(一) AJAX技术对于前段或者后端工程师来说,都是必不可缺的 那我们这几期都来细细品味一下AJAX的相关知识,直接上干货喽~ 1、什么是AJAX,为什么要使用Ajax(请谈一下你对Ajax的认识) 什么...

理性思考
49分钟前
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部