我正在Visual Studio中进行C++编码实践,并一直将此问题显示为标题。我知道问题在哪里发生,但我不知道为什么会发生以及如何解决。请帮我解决一下这个。
class_templete.h
typedef std::string QuestionName;
class ClassTemplete
{
public:
ClassTemplete(Question iQuestionName);
private
static std::map<QuestionName,ClassTemplete *> questionName_questionPointer_map_;
}
class_templete.cpp
map<QuestionName, ClassTemplete *> ClassTemplete::questionName_questionPointer_map_;
ClassTemplete::ClassTemplete(QuestionName iQuestionName)
{
ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this;
}
Chapter1_question1.h
class C1Q1 : public ClassTemplete
{
public:
C1Q1(QuestionName iQuestionName) : ClassTemplete(iQuestionName) {};
private:
static QuestionName question_name_;
static C1Q1 question_instance_;
}
Chapter1_question1.cpp
QuestionName C1Q1::question_name_ = "C1Q1";
C1Q1 C1Q1::question_instance_(C1Q1::question_name_);
我发现在运行程序时此地方发生了问题:
ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this;
但是,我无法解释为什么会这样。
如果需要更多信息,请随时与我联系。
亲切的问候,
易吉
最佳答案
QuestionName C1Q1:::question_name_
相对于ClassTemplate::questionName_questionPointer_map_
位于哪里?它们似乎都是具有静态存储持续时间的变量,即它们是在main()
运行之前构造的。但是,C++编译器/链接器仅使用一个翻译单元(在这种情况下,对象是从上到下构造),而不是在翻译单元之间(在这种情况下,对象以随机顺序来构造)来命令构造此类全局对象。
您的问题似乎是在ClassTemplate::questionName_questionPointer_map
之后构造了C1Q1::question_name_
。即,当构造C1Q1::question_name_
时,正在访问尚未构造的对象。
常规的解决方法是使static
对象成为其他对象而不是对象,而是依赖于带有本地static
变量的函数,并返回引用:
std::map<QuestionName,ClassTemplete *>&
ClassTemplete::questionName_questionPointer_map_() {
static std::map<QuestionName,ClassTemplete *> rc;
return rc;
}
(请注意,这种结构在不使用C++ 11时不是线程安全的;在使用C++ 11时是线程安全的)。