Мне было интересно, как как вы можете выполнять полиморфизм со ссылками, в отличие от указателей.
Чтобы уточнить, см. следующий минимальный пример:
class A;
class B {
public:
A& a; ///////////////// <- #1
B();
void doStuff();
};
class A {
public:
virtual void doSmth() = 0;
};
void B::doStuff() {
a.doSmth();
}
class A1 : public A {
public:
void doSmth() {
}
};
B::B() : a(
* ////////////// <- #2
(new A1) /////////// <- #3
) {
}
Это компилируется и работает, но в качестве наиболее важного пункта здесь следует, что a
в строке #1
является ссылкой, поэтому для того, чтобы иметь возможность использовать его полиморфно (это фактическое слово?), как показано в строке #3
Мне нужно "преобразовать указатель в ссылку", разыменовывая его.
Это кажется мне немного странным, и мне было интересно, есть ли лучший (в смысле чище) способ. Это только я?
Обоснование
Было бы здорово, если бы мне вообще не понадобился new
, но при объявлении (!) B
я не знаю, как создать экземпляр A1
(!), поскольку a
is передняя декларация - A1
реализована в том же компиляционном блоке, что и B
. Тем не менее, существует ли реальная потребность в распределении динамической памяти в этом случае? Как вы это сделаете?
Извините за слегка двоякий вопрос.
Изменить
Примечание: B
огромен (и я не могу сделать его класс шаблона), и выйдет за пределы области точно, когда программа завершится - a
будет маленькой и сделает два больших модуля разговаривать друг с другом, он понадобится, если существует экземпляр B
(есть только один).
Изменить 2
Я просто понял, что, поскольку оба a
и B
являются эффективными синглтонами, я могу просто создать экземпляр static
A1
в модуле компиляции B
, избегая динамического распределения памяти (даже если было два B
, они могли легко использовать один и тот же экземпляр a
). Справедливости ради, я не публиковал это как ответ, но согласен с ответом, который побудил меня придумать это решение.