Виртуальное членство в алмазном наследовании с указателями - PullRequest
0 голосов
/ 09 сентября 2018

Аналогично, но не идентично ЭТОМУ ВОПРОСУ :

    A
  /   \
 B     C
  \   /
    D

То, что я хочу, это:

struct A { virtual void func (void) = 0; };

struct B : virtual A { void func (void) {} };
struct C : virtual A { void func (void) {} };

struct D : B,C { void func (void) {} };

int main ()
{
    A *p = new D();
    ((C*) p)->func(); // do C::func
    ((B*) p)->func(); // do B::func
}

Согласно НАСТОЯЩЕМУ ВОПРОСУ это, похоже, не проблема, поскольку наследование - это просто множественное наследование, а не бриллиант. почему это не работает с ромбовидной формой?

Очевидно, это неоднозначно, но я хочу иметь возможность привести указатель и, следовательно, использовать другую родительскую реализацию виртуальной функции, т. Е .:

((C*) p)->func(); //does C::func

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

error: cannot convert from pointer to base class 'A' to pointer to derived class 'C' because the base is virtual
 ((C*)p)->func();

которую я пытался гуглить, но нигде не могу найти

1 Ответ

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

Поскольку func является виртуальным во всей иерархии, любой прямой вызов func через указатель на любой из задействованных типов вызовет D::func. Чтобы выполнить приведение кода в вопросе, используйте dynamic_cast<C*>(p). Но это не удаляет виртуальную сущность func, так что в итоге вызовет D::func, как это делает p->func().

Чтобы избавиться от виртуальности, вы должны назвать как класс, так и функцию. В более простом контексте:

D *d = new D;
d->C::func(); // calls C::func

Если у вас есть указатель на базовый тип вместо указателя на производный тип, вы должны преобразовать указатель в тип с C::func. Это преобразование выполняется с помощью dynamic_cast, например:

A *p = new D;
dynamic_cast<C*>(p)->C::func();

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

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