Проблема с инициализацией ссылки в конструкторе - PullRequest
0 голосов
/ 07 сентября 2018

Псевдоопределение класса:

Базовый виртуальный класс A:

class A {
public:
    virtual ~A();
    virtual void doSomething() const = 0;
};

Класс B Наследование от A:

class B : public A {
public:
    void doSomething() {} const;
}

Базовый виртуальный класс C:

class C {
public:
    virtual ~C();
    virtual void doSomething() const = 0;
};

Класс D, наследуемый от C:

class D : public C {
public:
    D(const &A _a = *A_Ptr(new B)) : a(_a) {}
    void doSomething() {} const;
private:
    const &A a;
}

A_Ptr - это typedef общего указателя класса A.

Моя проблема с объявлением другого класса.

Давайте назовем это классом X:

class X {
public:
    X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a)) : a(_a), c(_c) {}
private:
    const &A a;
    const &C c;
}

X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a)) - эта часть инициализации не работает. Что работает, это

X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D)

Но если я сделаю это таким образом, я создам два общих указателя типа класса A, чего я бы не хотел. С другой стороны, что-то вроде X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a)) или X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(_a)) не работает. Есть какой-нибудь известный способ решить эту проблему?

Заранее спасибо:)

1 Ответ

0 голосов
/ 07 сентября 2018

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

class D : public C {
public:
    D() : myA(new B), a(*myA) {}
    D(const &A _a) : a(_a) {}
    void doSomething() {} const;
private:
    std::unique_ptr<A> myA;
    const &A a;
}

Таким образом, D может быть создан без аргументов и будет корректно управлять временем жизни объекта, связанного с a, или он может быть создан с помощью A, предоставляемого извне, и сам ничего не создаст.

Аналогичное изменение можно сделать для X:

class X {
public:
    X() : myA(new B), a(*myA), myC(new D(a)), c(*myC) {}
    X(const &A _a) : a(_a), myC(new D(a)), c(*myC) {}
    X(const &A _a, const &C _c) : a(_a), c(_c) {}
private:
    std::unique_ptr<A> myA;
    const &A a;
    std::unique_ptr<C> myC;
    const &C c;
}

Обратите внимание, что в исходном коде были висячие ссылки, поскольку интеллектуальные указатели, созданные в качестве аргументов по умолчанию, выходят из области видимости после завершения выполнения конструктора. Вот почему они должны храниться где-то в классе, как показано в приведенном выше решении.

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