-2

I have explained in the comments of this code my problem. The compiler complains that root isn't initialized, however I initialize it in the brackets of the constructor. If I also used an initialization list, then I would be initializing it twice instead of once ? How to design this properly ?

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;
}
dimitris93
  • 4,155
  • 11
  • 50
  • 86
  • I recommend not using nested classes or structs until your knowledge is improved. Nested classes and structures add a level of complexity which you don't need at this time in your learning. – Thomas Matthews Apr 29 '16 at 20:18
  • @ThomasMatthews It makes no difference if `Node` is nested or not in this question though. Just tested it. – dimitris93 Apr 29 '16 at 20:21

3 Answers3

7

Since your Node doesn't have default constructor, you need to call proper Node constructor in initializer list of container class constructor.

One way to solve your problem (you need to do some calculations for Node) is to offload those calculations to the Node constructor itself, and pass the input data to Node constructor. Another way is to create a function inside Tree which would perform the calculations and call the function in initializer list.

Here is an example of second approach:

Tree::Tree(int arg) : Node(calc_node_arg(arg)) {}
SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • From what you say I think that the better solution is to add a default Node constructor instead ? What is the standard c++ convention to do this ? Why not fix it once and forall in the Node class ? – dimitris93 Apr 29 '16 at 20:25
  • @Shiro, only you know if it makes sense to have a default constructor for your class or not. Basically, it boils to the fact - does it make sense to construct the object without any input or such object will not be useful? In latter case, default constructor is not needed. – SergeyA Apr 29 '16 at 20:31
  • What exactly is the problem with the compiler here ? Why does it make a difference if I initialize my `root` through an initialization list or inside the constructor ? – dimitris93 Apr 29 '16 at 20:34
  • 1
    There is no problem with the compiler, but there is a problem with your language knowledge. What you have inside the constructor body is not inittialization, but assignment. Those two are very separate thing. It is perfectly reasonble, for example, for class to not have any assignment operator defined at all! – SergeyA Apr 29 '16 at 20:39
  • So you are saying that the "problem" here is the language itself, it all boils down to the feature that C++ offers, where you can overload the `=` operator ? Because if that feature wasn't available, I don't see any problem for the compiler to realize that the `=` operator means initialize instead of assign, in the context of a constructor... – dimitris93 Apr 29 '16 at 20:44
  • If C++ would be a language where constructors would not exist and only assignments are available, there would be no such issue. Such language exists, it is called C. (other such languages exist as well). – SergeyA Apr 29 '16 at 21:04
  • If you took the above code and wrote the equivalent to Java or C# it would compile just fine – dimitris93 Apr 29 '16 at 21:07
  • You would find yourself in a deep trouble if you try to compile such code in Java. I am not familiar with C#. – SergeyA Apr 29 '16 at 21:08
  • Compiled just fine... [pastebin](http://pastebin.com/pG0KKwSA). What do you mean ? – dimitris93 Apr 29 '16 at 21:17
  • `=` in Java does something which is very different from what `=` in C/C++ does. – SergeyA Apr 29 '16 at 21:19
  • The only difference that I can see is that in C++ you can overload the `=` operator. Other than that I don't see any differences. You assign a value to a variable. – dimitris93 Apr 29 '16 at 21:29
  • @Shiro Check here: http://stackoverflow.com/questions/869033/how-do-i-copy-an-object-in-java – SergeyA Apr 30 '16 at 11:29
  • That is basically overloading the `=` operator, as far as `=` is concerned. – dimitris93 Apr 30 '16 at 20:11
2

Use the member initializer list:

Tree.cpp

#include "Tree.h"

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

Otherwise the compiler generated code tries to default construct root which actually isn't possible.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • If you read my question, I am aware of that. And the problem is that that `1` is for the example's purposes. I mention that this `1` has to be *calculated* first. – dimitris93 Apr 29 '16 at 20:36
2

If you need to calculate i for the initialisation, why not define a function to do this:

e.g.

class Tree {
  // As before

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

Then

Tree::Tree() : root(DoCalc()) { }
Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • Ok, instead of `root(DoCalc())`, I think a better approach is to follow the answer of SergeyA and instead create a `Node` constructor that does the calculations there. So I would have something like `root(args)` instead. – dimitris93 Apr 29 '16 at 20:43