跨不同翻译单元的c++变量/实例初始化顺序

标签 c++ design-patterns initialization singleton translation-unit

提前致谢。

我在一些真实的项目中看到了这些代码。我只是简化了它们以在这里表达我的问题。基类将 this 指针放入其构造函数中的 vector(vec) 中。使用这个技巧,我们可以利用动态绑定(bind)在外部(在主函数中)调用派生类的方法。关键是把vector的定义放在Bash.h中,声明放在main.cpp中。

我的问题是,输出不是我想要的。为什么vec在一个Translation units(base.c,我们可以看到size是1),然后在其他Translation units(ma​​in.c,我们可以看到size变成了0),是不是又被初始化清空了?我想知道不同翻译单元的初始化顺序。似乎 Derive::dInstance 是第一个,然后 vec 是第二个,但为什么呢?

Base.h

#ifndef BASE_H
#define BASE_h

#include<iostream>
#include<vector>
using namespace std;
class Base{
    public:
        Base();
        virtual void speak();
};

#endif

Base.cpp

#include"Base.h"

vector<Base*> vec;
Base::Base() {
    vec.push_back(this);
    cout << "Base's constructor" << endl;
    cout << "Base() vector size: " << vec.size() << endl;**
}

void Base::speak() {
    cout << "I am Base" << endl;
}

Derive.h

#ifndef DERIVE_H
#define DERIVE_h
#include<iostream>
#include"Base.h"

class Derive: public Base {
    public:
        Derive();
        virtual void speak();

        static Derive dInstance;
};
#endif

Derive.cpp

#include "Derive.h"

// static member definition
Derive Derive::dInstance;

Derive::Derive() {
    cout << "Derived's construtor" << endl;**
}
void Derive::speak() {
    cout << "I am Derived" << endl;
}

main.cpp

#include<iostream>
#include"Base.h"

using namespace std;

extern vector<Base*> vec;
int main(int argc, char *argv[]) {
    cout << "vector size: " << vec.size() << endl;

    for(vector<Base*>::iterator iter = vec.begin(); iter != vec.begin(); iter++) {
        (*iter)->speak();
    }
}

输出:

Base's constructor
Base() vector size: 1
Derived's constructor
main() vector size: 0

最佳答案

这是static initialization order fiasco” .

translation units之间的初始化顺序static(或全局)变量未定义。所以想想如果 Derived.cpp 文件在 Base.cpp 之前初始化会发生什么,然后你添加到一个未初始化(构造)的 vector 导致 未定义的行为然后 vector 被初始化。

关于跨不同翻译单元的c++变量/实例初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33719322/

相关文章:

c# - 要求所有参数和所有参数命名的类构造函数

c++ - 为什么 fstream.open(filename) 使用文字而不是生成的字符串?

c++ - Qt -Timers 只能用于以 QThread 启动的线程

c++ - 如何检查我的程序是否由用户以管理员身份运行(Vista/Win7,C++)

objective-c - Objective-C 装饰器模式的简单实现

c++ - 如何初始化此结构?

c++ - 使用可变参数模板将指针传递给成员

design-patterns - 贫血领域模型与领域模型

c++ - 如何使用 C++11 <thread> 设计一个从源中提取数据的系统

java - log4j如何自初始化