Добавление virtual удаляет ошибку: тип 'base' не является прямой базой производного класса - PullRequest
4 голосов
/ 07 декабря 2011

Рассмотрим следующий пример кода:

#include <iostream>

using namespace std;

class base
{
   public:
      base()
      {
         cout << "ctor in base class\n";
      }
};

class derived1 : public base
{
   public:
      derived1()
      {
         cout <<"ctor in derived1 class\n";
      }
};

class derived2 : public derived1
{
   public:
      derived2() : base()
      {
         cout << "ctor in derived2 class\n";
      }
};

int main()
{
   derived2 d2obj;
   return 0;
}

Это дает ошибку:

ошибка: тип `base 'не является прямой базой для` output2'

Почему происходит эта ошибка? Если я сделаю базовый класс виртуальным, ошибки больше не будет. В чем причина этого?

Ответы [ 3 ]

7 голосов
/ 07 декабря 2011

Потому что base не является прямой базой derived2. Вы должны дать конструктор для ваших прямых баз, derived1 в этом случае.

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

Проблема возникает, когда у вас есть деривационный граф, который не является деревом. IBM имеет красивую картинку. Если вы не сделаете базу (V в примере) виртуальной (везде), у вас будет несколько копий. Если вы сделаете его виртуальным везде, у вас будет только одна копия, но тогда прямые потомки не смогут запустить конструктор (он будет запускаться> 1 раз), а класс листьев должен. Для получения более подробной информации лучше всего искать в Интернете.

2 голосов
/ 07 декабря 2011

Изменение

class derived2 : public derived1
{
   public:
      derived2() : base()
      {
         cout << "ctor in derived2 class\n";
      }
};

до

class derived2 : public derived1
{
   public:
      derived2() : derived1()
      {
         cout << "ctor in derived2 class\n";
      }
};

Это потому, что вы пытаетесь вызвать base1 конструктор из внучатого потомка производный2 .

Если вы измените деривацию производного1 от базового1 на виртуальный. Можно вызывать base1 из производного 2. Подробнее здесь.

0 голосов
/ 07 декабря 2011

Вы получили 1 между. Вы можете позвонить только ближайшим родителям в списке инициализаторов

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