提前感谢。
我在一些真实的项目中看到了这些代码。我只是简化了它们来表达我的问题。基类将this指针放入其构造函数中的向量(vec)中。使用这个技巧,我们可以利用动态绑定在外部(在main func中)调用派生类的方法。关键是将向量定义放在Bash.h中,并将声明放在main.cpp.中
我的问题是,输出不是我想要的。为什么vec被初始化并在一个翻译单元中使用(base.c,我们可以看到大小是1),然后在其他翻译单元中(main.c Base.h 基本.cpp 衍生.h 衍生.cpp main.cpp 输出:#ifndef BASE_H
#define BASE_h
#include<iostream>
#include<vector>
using namespace std;
class Base{
public:
Base();
virtual void speak();
};
#endif
#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;
}
#ifndef DERIVE_H
#define DERIVE_h
#include<iostream>
#include"Base.h"
class Derive: public Base {
public:
Derive();
virtual void speak();
static Derive dInstance;
};
#endif
#include "Derive.h"
// static member definition
Derive Derive::dInstance;
Derive::Derive() {
cout << "Derived's construtor" << endl;**
}
void Derive::speak() {
cout << "I am Derived" << endl;
}
#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的构造函数Base()矢量大小:1派生的构造函数main()向量大小:0
这是"static
初始化顺序的惨败"。
static
(或全局)变量的转换单元之间的初始化顺序未定义。因此,考虑一下如果Derived.cpp
文件在Base.cpp
之前初始化,然后添加到未初始化(构造)的向量中,导致未定义的行为,然后初始化向量会发生什么。
起初,根据不同的翻译单位,初始化顺序没有规则。
并且,全局变量和全局静态变量将在主函数之前初始化。属于函数FuncA()的局部静态变量将在第一次调用FuncA时初始化。