Допустимо ли использовать this в конструкторе базового класса? - PullRequest
2 голосов
/ 15 февраля 2012

Я пытаюсь создать базовый класс, для которого все производные от него будут автоматически зарегистрированы в другом классе, например:

class System;
class Object
{
public:
    Object()
    {
        System sys;
        sys.AddObject(this);
    }
    virtual ~Object()
    {
        System sys;
        sys.RemoveObject(this);
    }
};
class System
{
public:
    // Some other processing function which operates on all things derived
    // from Object at one time.
    void ProcessAllObjectsInExistence();

    void AddObject(Object *o)
    {
        list.push_back(o);
    }
    void RemoveObject(Object *o)
    {
        std::vector<Object *>::iterator i = find(list.begin(), list.end(), o);
        if (*i != list.end()) list.erase(i);
    }
private:
    static std::vector<Object *> list;
};

Это законно и определено? Причина, по которой я спрашиваю, заключается в том, что после чтения и записи в элементы данных Object (не показанные здесь) изнутри ProcessAllObjectsInExistence().

я получаю несколько забавных ошибок.

т.е. для одного Object перед тем, как я вызову System.ProcessAllObjectsInExistence(), членами являются 0 и 100, а затем первая строка внутри ProcessAllObjectsInExistence() является строкой отладки, которая печатает элементы и отображает 0 и 0. болезненный> <</p>

Ответы [ 2 ]

4 голосов
/ 15 февраля 2012

Да, он хорошо определен для доступа к this при создании базового класса.

Следует помнить одну вещь: во время конструктора (или деструктора) тип *this является классом, находящимся в стадии разработки, , а не типом, который полностью построенный объект будет в конечном итоге иметь. Основным следствием этого является то, что виртуальные функции будут отправляться в соответствии с их определениями в базовом классе, и нельзя вызывать чисто виртуальную функцию.

Конечно, вызов AddObject - это нормально, поскольку он вообще не получает доступ к объекту в процессе строительства. Единственный способ понять, что ваш код работает неправильно, - это если вы вызываете ProcessAllObjectsInExistence() из другого потока при создании объекта, что было бы очень плохо, поскольку нет блокировки для защиты доступа к списку.

3 голосов
/ 15 февраля 2012

Совершенно верно ссылаться на this внутри Базового класса.
Однако вызов виртуальных методов (если они у вас есть) внутри базового класса на самом деле не будут работать так, как вы думаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...