2016-04-29 5 views
-2

Я объяснил в комментариях этого кода мою проблему. Компилятор жалуется, что root не инициализирован, однако я инициализирую его в скобках конструктора. Если я также использовал initialization list, то я бы инициализировал его дважды вместо одного? Как правильно это сделать?Инициализация членов класса

tree.h

class Tree 
{ 
public: 
    Tree(); 
    ~Tree(); 

private: 
    struct Node 
    { 
     Node(int i); 
     int i; 
    }; 

    Node root; 
}; 

Tree.cpp

#include "Tree.h" 

Tree::Tree() // <---- Complains that root isn't initialized 
/* An initialization list here fixes the problem, however 
* that wouldn't be convinient because I need to calculate the arguments of 
* the Node first... So if I used both an initializer list here 
* and then I also initialize the root AGAIN in the brackets bellow, 
* wouldn't I be executing more code for no reason ? 
*/ 
{ 
    root = Node(1); // initialize root 
} 

Tree::~Tree() 
{ } 

Tree::Node::Node(int i) : 
{ 
    i = 1; 
} 
+0

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

+0

@ThomasMatthews Не имеет значения, если «Node» вложен или нет в этом вопросе. Просто протестировал его. – dimitris93

ответ

7

Так как ваш Node не имеет конструктор по умолчанию, вам нужно вызвать надлежащий Node конструктор в списке инициализации контейнера класса.

Один из способов решения вашей проблемы (вам нужно выполнить некоторые вычисления для узла) - это разгрузить эти вычисления самому конструктору узла и передать входные данные в конструктор Node. Другой способ - создать функцию внутри Tree, которая будет выполнять вычисления и вызывать функцию в списке инициализаторов.

Вот пример второго подхода:

Tree::Tree(int arg) : Node(calc_node_arg(arg)) {} 
+0

Из того, что вы говорите, я думаю, что лучшим решением является добавление конструктора Node по умолчанию вместо этого? Что такое стандартное соглашение C++ для этого? Почему бы не исправить его один раз и forall в классе Node? – dimitris93

+0

@Shiro, только вы знаете, имеет ли смысл иметь конструктор по умолчанию для вашего класса или нет. В принципе, это сводится к тому, что имеет смысл построить объект без какого-либо ввода, или такой объект не будет полезен? В последнем случае конструктор по умолчанию не нужен. – SergeyA

+0

В чем проблема с компилятором? Почему это имеет значение, если я инициализирую свой «корень» через список инициализации или внутри конструктора? – dimitris93

2

Используйте список элемент инициализатора:

Tree.cpp

#include "Tree.h" 

Tree::Tree() : root(1) { 
} 

В противном случае компилятор сгенерированный код пытается по умолчанию конструкт root который фактически невозможно.

+0

Если вы прочтете мой вопрос, я знаю об этом. И проблема в том, что это '1' для целей примера. Я упоминаю, что этот '1' должен быть * рассчитан * первым. – dimitris93

2

Если вам нужно вычислить i для инициализации, то почему бы не определить функцию, чтобы сделать это:

например

class Tree { 
    // As before 

    static int DoCalc() { 
    int i = 0; 
    // some maths to calculate i; 
    return i; 
}; 

Тогда

Tree::Tree() : root(DoCalc()) { } 
+0

Хорошо, вместо 'root (DoCalc())', я думаю, что лучший подход состоит в том, чтобы следовать ответу SergeyA и вместо этого создавать конструктор «Node», который выполняет вычисления там. Поэтому вместо этого у меня было бы нечто вроде «root (args)». – dimitris93