0

I have a class called Tree with three instance variables called board (Board), root (Node) and end (Point). Additionally it has a constructor of six parameters. I want to create the objects inside the constructor and assign them to the references (the instance variables).

When I try to assign the root I get function "Node::operator=(const Node &)" (declared implicitly) cannot be referenced -- it is a deleted function error.

I did some research and it seems you have to construct reference variables in the constructor initializer, but I cannot figure out how without changing the parameters. I know (kinda) how the initalizer works, but the problem is in the constructor block. I would like to create the objects in the block and assign, since I cannot directly use the initializer without changing the parameters to the objects itself. If this code was Java then it would work.

/* HEADER FILE */
class Tree {
public:
    Tree(int boardHeight, int boardWidth, int knightStartXPosition,
    int knightStartYPosition, int knightEndXPosition, int knightEndYPosition);

private:
    Board& board; // Board has int height and int width.
    Node& root; // Node has location (Point) and end (Point)
    Point& end; // A point is a plane vector of x and y.

    void jumpNodes(Node* node); // not used yet
};
/* IMPLEMENTATION FILE */
Tree::Tree(int boardHeight, int boardWidth, int knightStartXPosition,
    int knightStartYPosition, int knightEndXPosition, int knightEndYPosition) {
        Point start = Point(knightEndXPosition, knightEndYPosition);
        Point end = Point(knightStartXPosition, knightStartYPosition);
        Node root = Node(start, end);

        this->board = Board(boardHeight, boardWidth);
        this->root = root; // this line gives the error
        this->end = end;
};

The expected solution is the constructor works with given parameters, but if it is not possible, I need to inputs and structure.

treeden
  • 675
  • 1
  • 6
  • 17
  • Change to `Board board; Node root; Point end;` . Declaring a variable as reference means it will refer to an object that already exists – M.M Nov 07 '19 at 20:33
  • Does this answer your question? [C++ Member Initialization List](https://stackoverflow.com/questions/7665021/c-member-initialization-list) – JVApen Nov 07 '19 at 20:33
  • If you intend to create the variables in your constructor (good idea) then making them references was the wrong choice. The reason is given in the comment byx M.M. – Yunnosch Nov 07 '19 at 20:36

2 Answers2

0

First of all, you are assigning temporaries/locals to a reference, thus the reference would be invalidated right after the contructor, because the objects they refer to, get out of scope

Second, a refence is like an immutable pointer (a Pointer that cannot Change what its pointing to) and your reference members are already initialized when the function Body ist entered, thus they cannot be re-pointed.

To initialize a member reference properly use an initalization list:

Foo::Foo(int& bar, float& baz) : m_bar(bar), m_baz(bar) {...}

Where Foo ist the class name, bar and baz arguments and m_bar and m_baz are members. Note the : and &

Also i think in your Case you actually want to Store them by value, atleast i see no reason for a reference, since all Arguments are passed by value. A reference needs to refer Something, that somewhere has to be stored

ich.
  • 17
  • 4
0

First of all you should not use reference members for this purpose. They are for when the name should refer to an object that already exists.

The class could look like:

class Tree {
public:
    Tree(int boardHeight, int boardWidth, Point knightStart, Point knightEnd);

private:
    Board board;
    Node root;
    Point end;
};

/* IMPLEMENTATION FILE */
    Tree::Tree(int boardHeight, int boardWidth, Point knightStart, Point knightEnd)
        : Board(boardHeight, boardWidth), root(knightStart, knightEnd), end(knightEnd) {}

which you can see is a lot simpler than what you currently have . In fact it would be common practice to have the constructor body inline in the header since it only initializes members and doesn't do anything complicated.

When I try to assign the root I get function "Node::operator=(const Node &)" (declared implicitly) cannot be referenced -- it is a deleted function error.

This message likely indicates that you have done a similar thing in the Node class , i.e. used reference variables as members, which disables implicit assignment (see here for the reason). You should redesign your other classes to not use references in this way either.

Furthermore, you should get other error messages before the one you quoted. Specifically, that you didn't initialize the reference members. Generally speaking when you have multiple errors you should focus on fixing the first one first, as often the other errors are consequential from the first one and will disappear once the first one is gone.

If this code was Java then it would work.

C++ is different to Java and you had better get used to the fact. If you use a member of type std::shared_ptr<Board> instead of Board then it will have similar (but not identical) semantics to Java references. However this would be considered poor style in C++ unless you specifically intend for a single board object to be shared amongst multiple Trees.

In C++ a reference variable does not perform lifetime management on the object that you bind to it; and furthermore it must be bound on initialization and it is not possible to rebind. Hopefully it is clear that this is not suitable for the way you are using it. It has a different purpose and behaviour to a Java reference despite having the same name.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • I knew that references had to be initialized at the beginning since they cannot be null, but I think my mindset were in other languages than required for c++, hence the reason I wanted to do it in the block of the constructor. – treeden Nov 09 '19 at 14:46