Как исправить «ошибку: нет подходящей функции для вызова» при двойном наследовании от базового класса - PullRequest
5 голосов
/ 17 мая 2019

В настоящее время я пытаюсь реализовать иерархию унаследованных классов в моем проекте.Поэтому я использую члены initializer-lists и "pipe" - ссылку на переменную вплоть до базового класса.Я действительно не уверен, почему я получаю ошибку компилятора.

Я уже пытался изменить ссылку "int & id" на указатель "int * id".Приведенный ниже пример является лишь минимальным примером, который указывает на мою проблему:

class Base
{
public:
    int& m_id;

    Base(int &id)
        : m_id(id)
    {
    }
};

class Derived1: virtual public Base
{
public:
    Derived1(int &id) : Base(id)
    {
    };
};

class Derived2: public Derived1
{
public:
    Derived2(int &id) : Derived1(id)
    {
    };
};

int main()
{
   int i = 13;
   Derived2 Test(i);
}

При попытке компилирования я получаю следующее сообщение об ошибке:

"error: нет соответствующей функции для вызоваto 'Base :: Base ()' "

Есть идеи, что я делаю не так?

Спасибо за помощь.

Ответы [ 2 ]

2 голосов
/ 17 мая 2019

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

class Derived2: public Derived1
{
public:
    Derived2(int &id) : Base(id), Derived1(id)
    {
    }
};
2 голосов
/ 17 мая 2019

Виртуальное наследование и виртуальные функции - разные понятия.

Виртуальное наследование является особенным в том смысле, что виртуальные базы должны быть явно инициализированы всеми производными классами.В этом случае Derived2 пытается делегировать инициализацию Base в Derived1, но это недопустимо.Что на самом деле делает конструктор Derived2, так это вызывает конструктор по умолчанию Base из-за пропуска mem-initializer , который инициализирует Base.

. Вы должны вызватьконструктор Base в явном виде:

class Derived2 :public Derived1 {
public:
    Derived2(int &id) : Base(id), Derived1(id)
    {
    };
};

Конечно, если Derived1 не должен был быть фактически производным от Base, то производные классы Derived1 могут просто полагаться на Derived1 'Конструктор s для инициализации Base.Таким образом, другое исправление, в зависимости от вашей ситуации, состоит в том, чтобы просто удалить virtual в base-спецификаторе :

class Derived1 :public Base {
public:
    Derived1(int &id) :Base(id)
    {
    };
};

class Derived2: public Derived1 {
public:
    Derived2(int &id) :Derived1(id)
    {
    };
};
...