У меня есть класс Controller
, внутри которого есть класс Button
. Controller
содержит несколько Button
экземпляров разных типов (например, button_type_a
, button_type_b
).
controller.h
#ifndef __controller__
#define __controller__
class Controller
{
public:
class Button
{
public:
Button(int type = -1);
private:
int type;
};
Controller();
Button A;
Button B;
Button X;
Button Y;
};
#endif
Типы кнопок int
s, и я хотел бы иметь возможность связать определенные типы кнопок int
s с указателями на Button
экземпляров этих конкретных типов.
Чтобы отслеживать эту ассоциацию, я использую std::map<int, Controller::Button*>
, который я typedef
на buttonmap_t
.
Когда я создаю новые Button
экземпляры (в конструкторе Controller
), конструктор Button
регистрирует типы этих Button
с картой.
controller.cpp
#include "controller.h"
#include <map>
typedef std::map<int, Controller::Button*> buttonmap_t;
buttonmap_t map;
Controller::Controller() :
A(0),
B(1),
X(2),
Y(3)
{ }
Controller::Button::Button(int type) :
type(type)
{
map[type] = this;
}
Затем я создаю глобальный объект Controller
и определяю main()
.
main.cpp
#include <iostream>
#include "controller.h"
Controller controller;
int main(int argc, const char * argv[])
{
std::cout << "running..." << std::endl;
return 0;
}
В зависимости от порядка, в котором я компилирую исходники, программа либо работает нормально, либо вызывает ошибку сегментации:
apogee:MapTest$ gcc controller.cpp main.cpp -o maptest -lstdc++
apogee:MapTest$ ./maptest
running...
apogee:MapTest$ gcc main.cpp controller.cpp -o maptest -lstdc++
apogee:MapTest$ ./maptest
Segmentation fault: 11
Похоже, что последний случай пытается использовать карту до того, как она была должным образом инициализирована, и это вызывает ошибку сегмента. Когда я отлаживаю с помощью Xcode, отладчик останавливается на «__tree», поскольку std::map
вызывает __insert_node_at()
, который выдает EXC_BAD_ACCESS(code=1, address=0x0)
. Стек вызовов показывает, что это было инициировано первым Button
экземпляром, вызвавшим map[type] = this;
.
Итак, вот мой вопрос, состоящий из нескольких частей:
- Почему это происходит из-за порядка компиляции?
- Есть ли способ добиться такого преобразования
int
вButton*
, на которое не влияет порядок компиляции? - Если так, то, что это?
В идеале я бы по-прежнему хотел, чтобы весь код, связанный с Controller
и Button
, был в отдельных файлах controller. *.
Похоже, это как-то связано (но не совсем так) со следующими вопросами: