Глобальные объекты и статические члены класса - PullRequest
0 голосов
/ 25 октября 2018

Я создал класс, в котором есть статический член.Каждый раз, когда создается объект, я хочу добавить указатель на этот объект в статическом члене.

Заголовочный файл:

#include <vector>

class A
{
public: 
    A(const int pin);
    ~A();
    static std::vector<A*> channels;

private:
    int pin_number;
}

cpp файл:

 #include "A.h"

 std::vector<A*> A::channels;

 A::A(const int pin) : pin_number(pin) { A::channels.push_back(this); };
 A::~A() { 
     std::vector<A*>::iterator ch = std::find(A::channels.begin(), A::channels.end(), this);
     if (ch != A::channels.end()) {
        A::channels.erase(ch);

 }

В main.cpp я хочу объявить объект.Однако, когда я объявляю и инициализирую как глобальную переменную, она, похоже, не работает:

A a1{ 1 };
A a2{ 2 };

int main() {
    std::cout << "Vector size: " << A::channels.size() << std::endl;
}

Вышеупомянутый код, похоже, не работает.В конструкторе объекта я вижу заполненный вектор.Выход 0 в приведенном выше случае.

Для 2 приведенных ниже примеров кода, похоже, все же работает.

Образец 1:

A *a1;
A *a2;

int main() {
    a1 = new A{ 1 };
    a2 = new A{ 2 };

    std::cout << "Vector size: " << A::channels.size() << std::endl;
} 

Образец 2:

int main() {
    A a1{ 1 };
    A a2{ 2 };

    std::cout << "Vector size: " << A::channels.size() << std::endl;
}

В приведенных выше 2 случаях выводится 2, что я и ожидал.

Может кто-нибудь помочь мне объяснить, что я делаю неправильно или чего мне не хватает.Я предполагаю, что это как-то связано с областью действия объектов, но я не могу понять, почему первый пример не работает.

Редактировать: я не добавил деструктор для класса, так как не думал, что он уместен для этого вопроса.

Ответы [ 2 ]

0 голосов
/ 25 октября 2018
A a1{ 1 };
A a2{ 2 };

int main() {
    std::cout << "Vector size: " << A::channels.size() << std::endl;
}

В A a1 { 1 }; и A a2 { 2 }; объекты созданы глобально.Где, как указатель, версия имеет указатели, созданные глобально, но объекты, созданные в куче, а не в глобальном пространстве.Это то же самое для вашего другого примера.Член channel в классе A является статическим по отношению к A.cpp, но объекты создаются в Main.cpp глобально.Это означает, что если вы хотите, чтобы счетчик обновлялся правильно, вам нужно поместить std::vector<A*> A::channels; в main.cpp, а не в A.cpp

0 голосов
/ 25 октября 2018

С глобальным объектом у вас классическая проблема - порядок инициализации глобальных объектов из разных модулей компиляции не определен, поэтому в этом случае кажется, что ваш вектор инициализируется после того, как эти 2 экземпляра созданы.Решение состоит в том, чтобы иметь статический локальный вектор:

class A
{
public: 
    A(const int pin) { A::channels().push_back(this); };

    static std::vector<A*> &channels() 
    {
        static std::vector<A*> theInstance;
        return theInstance;
    }
}

, чтобы ваша проблема с порядком инициализации была решена.

Примечание: если неясно, почему это решение работает, вы можете посмотреть на это ответ - ваша проблема связана с проблемой реализации одноэлементного паттерна, и она там глубоко решена.

...