Question

I am doing a C++ coding practice in Visual Studio and keep having this problem shown as title. I know where the problem happens but I don't why it happens and how to solve it. Please help me with this.

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_);

I found out that problem happens at this place when I run the program:

ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this;

However, I cannot explain why it happens.

Please feel free to contact me if more information is required.

Kind regards,

Yi Ji

Was it helpful?

Solution

Where is QuestionName C1Q1:::question_name_ located relative to ClassTemplate::questionName_questionPointer_map_? They seem to be both variables with static storage duration, i.e., they are constructed before main() is run. However, the C++ compiler/linker orders the construction of such global objects only with one translation unit (in which case the objects are constructed top to bottom), not between translation units (in which case the objects are constructed in a random order).

You problem looks as if ClassTemplate::questionName_questionPointer_map would be constructed after C1Q1::question_name_. That is, when C1Q1::question_name_ is constructed, an object which is not, yet, constructed is being accessed.

The conventional fix is to make the static object other objects depend on not an object but rather a function with a local static variable to which a reference is returned:

std::map<QuestionName,ClassTemplete *>&
ClassTemplete::questionName_questionPointer_map_() {
    static std::map<QuestionName,ClassTemplete *> rc;
    return rc;
}

(note that this construction is not thread-safe when you don't use C++11; it is thread-safe when using C++11).

OTHER TIPS

You have to use std::map::insert, you can't do ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this; when you insert a new key in the map.

This code should work:

ClassTemplete::questionName_questionPointer_map_.insert(std::make_pair(iQuestionName, this));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top