Есть ли способ инициализации member_A
в классе ContainingClassB
таким, чтобы он был типа B?
Нет.member_A
является членом ContainingClassA
.ContainingClassB
использует тот же member_A
из родительского класса, ContainingClassA
.Вы не можете изменить макет родительского класса.
Также вы не можете изменить объявление виртуальной функции (за некоторыми исключениями).Другими словами, вы не можете переопределить A get()
с помощью B get()
.
Вы можете изменить get()
, чтобы вместо него возвращать ссылку , тогда можно будет переопределить A& get()
с B& get()
(поскольку A&
и B&
являются ковариантными типами).
Но сначала вам нужно разделить решение на «интерфейс» и две «реализации» для A и B:
#include <iostream>
struct A {
int a = 0;
};
struct B : public A {
int b = 1;
};
class ContainingClassBase {
public:
virtual const A& get() = 0;
};
class ContainingClassA : public ContainingClassBase {
A member_A;
public:
virtual const A& get() override { return member_A; }
};
class ContainingClassB : public ContainingClassBase {
B member_B;
public:
virtual const B& get() override { return member_B; }
};
int main() {
ContainingClassA a;
ContainingClassB b;
std::cout << a.get().a << std::endl;
std::cout << b.get().b << std::endl;
}
Обратите также внимание, что решение с выделением A
отдельно и сохранением указателя на него не очень эффективно, поскольку трудно избежать выделения ложного A
при построении ContainingClassB
(конструктор ContainingClassA
будет по-прежнему вызываться первым).