2017-02-06 3 views
0

У меня есть следующие классы, которые образуют многоуровневую модель наследования.Множество уровней наследования и вызывающих базовых конструкторов в C++

class CavPkoTest : virtual public CavTest 
{ 
public: 
    CavPkoTest() : CavTest{CAV_TEST_ID_PKO}, NpBaseTest{CAV_TEST_ID_PKO, MODULE_CAV_TEST} {} 
} 
class CavTest : virtual public NpBaseTest 
{ 
public: 
    CavTest(uint16_t p_testId) : NpBaseTest{p_testId, MODULE_CAV_TEST} {} 
} 

class NpBaseTest 
{ 
    uint16_t m_testId; 
    uint16_t m_moduleType; 
public: 
    NpBaseTest(uint16_t p_testId, uint16_t p_moduleType) : m_testId{p_testId}, m_moduleType{p_moduleType} {} 
} 

Мой вопрос заключается в том, что когда CavPkoTest() (листовой узел) вызывается конструктор, он делегирует на вызов его конструктора родительского класса CavTest(). CavTest() конструктор объявляется, что явно вызывает его родительский конструктор NpBaseTest(). Итак, почему мне требуется явно вызвать конструктор NpBaseTest() от CavPkoTest(), когда вызов для конструктора CavTest() должен сделать это для меня?

Если я объявляю CavPkoTest() конструктор как:

class CavPkoTest : virtual public CavTest 
{ 
public: 
    CavPkoTest() : CavTest{CAV_TEST_ID_PKO} {} 
} 

FYI: Оба CavTest и NpBaseTest классы абстрактных базовых классов, так как они имеют 1+ чистые функции виртуальных членов (которые реализуются CavPkoTest класса)

+0

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

ответ

1

При виртуальном наследовании вы можете иметь несколько базовых классов, исходящих из одного и того же виртуального базового класса.

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

Если базовые классы должны были инициализировать такой жевиртуальный базовый класс, они в конечном итоге инициализируют его несколько раз.

+0

Как насчет 'CavTest (uint16_t p_testId): NpBaseTest {p_testId, MODULE_CAV_TEST} {}'? Похоже, это потерянное объявление, в котором я перехожу в «MODULE_CAV_TEST», когда мне нужно сделать это снова в дочернем классе. Я имею в виду, могу ли я избежать использования неявного конструктора для 'CavTest'? – nitimalh

+0

@nitimalh 'CavTest' не знает, была ли инициализирована' NpBaseTest', потому что между ними могут быть несколько под-объектов базового класса CavTest и только один 'NpBaseTest', разделяемый между ними. –

+0

А-а-а-а-а-а-а-а-а-а-а-а-а-а. Мне не нужно передавать MODULE_CAV_TEST в конструкторе CavTest. Я мог бы просто объявить его как «CavTest (uint16_t p_testId): NpBaseTest {p_testId, 0} {}' – nitimalh