2016-03-13 3 views
1

Я произвел минимальный пример для тиражирования проблемы я вижу, с более сложной структурой иерархии классов:C++ Многократное наследование pproblem с чисто виртуальными функциями

#include <string> 
#include <iostream> 


class A 
{ 
protected: 

    virtual 
    ~A() = 0; 

}; 

inline 
A::~A() {} 

class B : public A 
{ 
public: 

    virtual 
    ~B() 
    { 
    } 

    std::string B_str; 
}; 

class BB : public A 
{ 
public: 

    virtual 
    ~BB() 
    { 
    } 

    std::string BB_str; 
}; 

class C : public A 
{ 
protected: 

    virtual 
    ~C() 
    { 
    } 

    virtual 
    void Print() const = 0; 
}; 

class D : public B, public BB, public C 
{ 
public: 

    virtual 
    ~D() 
    { 
    } 
}; 

class E : public C 
{ 
public: 

    void Print() const 
    { 
     std::cout << "E" << std::endl; 
    } 
}; 

class F : public E, public D 
{ 
public: 

    void Print_Different() const 
    { 
     std::cout << "Different to E" << std::endl; 
    } 

}; 


int main() 
{ 

    F f_inst; 

    return 0; 
} 

Compiling с g++ --std=c++11 main.cpp производит ошибку:

error: cannot declare variable ‘f_inst’ to be of abstract type ‘F’ 

    F f_inst; 

note: because the following virtual functions are pure within ‘F’: 

    class F : public E, public D 
     ^
note: virtual void C::Print() const 

    void Print() const = 0; 
     ^

Поэтому компилятор считает, что Print() является чистым виртуальным.

Но, я указал, что Print() должно быть в class E.

Итак, я неправильно понял некоторые правила наследования.

Каково мое недоразумение и как я могу исправить эту проблему?

Примечание: он скомпилирует, если я удалю наследование : public D от class F.

+1

'F' также получен из' D', а 'D' - из' C', а 'C :: Print' в этом экземпляре' C' не был переопределен. –

+1

Одним из вариантов является использование виртуального наследования, что означает, что 'F' имеет только одного предка' C', а 'D' и' E' делят базу 'C'. Поисковым термином является «проблема наследования алмазов» –

+0

@ M.M 'class D' используется как абстрактный базовый класс для вектора указателей базового класса. Я не могу реализовать функцию 'Print()' в 'классе D'. Что мне делать? – user3728501

ответ

2

В настоящее время ваш F происходит от C двумя различными способами. Это означает, что объект F имеет две отдельные базы C, и поэтому есть два экземпляра C::Print().

Вы только переопределяете тот, который приходит через E.

Чтобы решить эту проблему вы должны принять один из следующих вариантов:

  • также переопределить идущему через D, либо путем реализации D::Print() или F::Print()
  • Сделать Print без чистого
  • Использование виртуальной наследование, так что есть только одна база C.

Для последнего варианта, корректировки синтаксиса будет:

class E : virtual public C 

и

class D : public B, public BB, virtual public C 

Это означает, что D и E будут иметь одинаковый C экземпляр в качестве своего родителя, и поэтому переопределение E::Print() переопределяет функцию для всех «вниз по течению» этого C.

Дополнительную информацию см. В разделе «Проблема наследования алмазов». См. Также Multiple inheritance FAQ

Смежные вопросы