2012-04-03 2 views
0
class A // abstract class 
{ 
protected: 
    int m_iA; 
    int m_iB; 
    int m_iC; 
    int m_iD; 
    int m_iE 
    ~A(); 
}; 

class B : public A // abstract class 
{ 
protected: 
    double m_dA; 
    double m_dB; 
    double m_dC; 
    double m_dD; 
    ~B(); 
}; 

class C : public B 
{ 
public:  
    C(int iA, int iB, int iC, int iD, int iE, double dA, double dB, double dC, double dD) 
    { 

    } 
} 

Вопрос> Как вы можете видеть выше, например, как базовый класс A и B содержат много переменных-членов. Какое лучшее решение передать эти начальные значения из класса C до базовых классов?, который является лучшим местом для инициализации переменных-членов базового класса?

Метод1> Назначить переменные элемента базового класса непосредственно внутри тела конструктора класса C.

Метод2> Передайте все начальные значения от конструктора C до B, а затем, наконец, до A.

Спасибо

+0

Существует третий вариант, который вы не упомянули: передать (const ссылки на) полностью построенные объекты типа A и B в конструктор C. –

ответ

5

Я бы рекомендовал сделать конструкторы для A и B и заставить их взять значения инициализации и применить их. Тогда C вызывает конструктор B, передавая ему значения и т. Д. Таким образом, если есть какой-либо другой класс, наследующий от B или A, он следует одному и тому же шаблону, и это может быть принудительно реализовано, только имея конструкторы, которые требуют значений инициализации.

+2

Вы делаете очень хорошую точку - если A или B добавляет новый член, добавление нового параметра в конструктор гарантирует, что они правильно построены или вы получите ошибки компиляции. –

2

Создать конструктор для базовых классов, которые принимают значение инициализации, и использовать их в списке инициализации конструктора C «s.

2

Использование C++ 11, вы можете уйти с немного меньшими затратами, чем вы ожидали:

class A { // abstract class 
protected: 
    int m_iA; 
    int m_iB; 
    int m_iC; 
    int m_iD; 
    int m_iE 
    A(int iA, int iB, int iC, int iD, int iE) 
     : m_iA(iA), m_iB(iB), m_iC(iC), m_iD(iD), m_iE(iE) {} 
    ~A(); 
}; 

class B : public A { // abstract class 
protected: 
    double m_dA; 
    double m_dB; 
    double m_dC; 
    double m_dD;  
    B(int iA, int iB, int iC, int iD, int iE, double dA, double dB, double dC, double dD) 
     : A(iA,iB,iC,iD,iE), m_dA(dA), m_dB(dB), m_dC(dC), m_dD(dD) {} 
    ~B(); 
}; 

class C : public B { 
public: 
    using B::B; 
} 
+0

Мне пришлось прочесть весь путь до конца, чтобы увидеть пуанлинг. –

+0

@MarkRansom: Спасибо за подсказку. Я попытался сделать * punchline * более заметным, свернув некоторые строки (теперь вам больше не нужно прокручивать). – bitmask

1

Чем лучше идея заключается в том, чтобы взять tuple, array или выборочную-структуру, которая содержит значения инициализации, и затем распакуйте его в конструкторе для B и A. Тогда конструктору C нужно только взять два объекта.

+0

Это, безусловно, альтернатива. Это может быть или не быть «лучшей идеей» в зависимости от данных. –

0

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