Ошибка компиляции при использовании множественного наследования - PullRequest
0 голосов
/ 02 октября 2019

Не могу скомпилировать мою программу. По историческим причинам у меня есть немного «сложная» иерархия классов в моем приложении. И теперь я столкнулся с другой проблемой: он не будет компилироваться из-за этой иерархии. Мой проект слишком велик, чтобы показать его здесь, но ниже вы можете увидеть пример, демонстрирующий проблему. Есть ли простой и элегантный способ это исправить? Каждый интерфейс / класс имеет действительно большое количество методов. Заранее спасибо.

struct ITest
{
    virtual ~ITest() {}
    virtual void a() = 0;
    // and many other methods
};

struct Test1 : public ITest
{
    virtual ~Test1() {}
    virtual void a() override {}
    // and many other methods overrides from ITest
    // plus a lot of other logic
};

struct ExtendedTest1 : public Test1
{
    virtual ~ExtendedTest1() {}
    // a lot of some other stuff
};

struct ITest2 : public ITest
{
    virtual ~ITest2(){}
    // and big count of the its methods and logic
};

struct MainClass : public ExtendedTest1, public ITest2
{
     virtual ~MainClass(){}
     // a lot of logic
};

int main()
{
    MainClass mainClassObj;
    return 0;
}

И ошибки:

main.cpp: In function ‘int main()’:
main.cpp:36:15: error: cannot declare variable ‘mainClassObj’ to be of abstract type ‘MainClass’
     MainClass mainClassObj;
               ^~~~~~~~~~~~
main.cpp:28:8: note:   because the following virtual functions are pure within ‘MainClass’:
 struct MainClass : public ExtendedTest1, public ITest2
        ^~~~~~~~~
main.cpp:4:18: note:    virtual void ITest::a()
     virtual void a() = 0;
                  ^

Не судите строго:)

UPD: перед тем, как задать этот вопрос, я действительно пробовал виртуальное наследование длярешить мою проблему, но это не сработало. Итак, после предложения попробовать еще раз, это работает) Итак, замена этих строк решила мою проблему:

struct Test1 : public ITest  --->  struct Test1 : virtual public ITest
struct ITest2 : public ITest ---> struct ITest2 : virtual public ITest

Я знаю, мы должны избежать виртуального наследования, но мы не можем, потому что по исторической причине и оченьбольшое количество кода

Спасибо всем за помощь!

Ответы [ 3 ]

2 голосов
/ 02 октября 2019

MainClass имеет два базовых класса, оба из которых получены (прямо или косвенно) из ITest. Таким образом, в MainClass есть два ITest подобъекта. Один из этих базовых классов обеспечивает переопределение для a, а другой (ITest2) - нет. Реализация в Test1 недоступна из ITest2. Поэтому MainClass потребуется предоставить реализацию.

Если вы хотите, чтобы Test1::a вызывался даже из подобъекта ITest2, вы можете MainClass перенаправить эти вызовы на Test1::a.

struct MainClass: public ExtendedTest1, public ITest2
{
    // ...
    void a() override { ExtendedTest1::a(); }
};

Другая возможность - виртуальное наследование .

2 голосов
/ 02 октября 2019

Вам необходимо Виртуальное наследование .

Виртуальное наследование может избавить от избыточных функций:

Вместо этого, если классы B и C наследуются практически от класса Aтогда объекты класса D будут содержать только один набор переменных-членов из класса A.

Если вы наследуете виртуально, вы избавитесь от дублированной абстрактной функции.

2 голосов
/ 02 октября 2019

Функция a является чисто виртуальной, поскольку она не реализована нигде в иерархии MainClass -> ITest2 -> ITest.

См. " Смертельный алмаз смерти"Проблема множественного наследования для дальнейшего обсуждения.

Самое простое решение - избегать такого рода наследования, если вы не совсем уверены в том, что делаете,Во-вторых, вы можете подумать о реализации a в MainClass, который перенаправляет аргументы в квалифицированный вызов на a в Test1, если это то, что вы ожидали.

...