0

So I have a parent Class which is:

class Node
{
public:
    Node();

    void setParentNode(Node* parent) {this->parentNode = parent;}
    Node* getParentNode() {return this->parentNode;}

    std::vector<Node> getChildNodes(){return this->childNodes;}

    void addChildNode(Node* node);
    void removeNode();

private:
    std::vector<Node*> childNodes;
    Node* parentNode = nullptr;
};

And a child inheriting from that class:

class Cube : public Node
{
public:
    Cube();
};

Now I have another file which has a function that uses the child class:

#include "cube.h"

void addCubes(){
     Cube mainCube;
     for(int i = 0; i < 10; i++){
         Cube c;
         mainCube.addChildNode(c);
      }
}

Problem is that mainCube doesn't see the addChildNode function which the parent has. What is the point of inheriting from another class if the parents functions aren't accessible from another place using the child class?

4
  • 2
    You probably wanna change addChildNode(Node node) to addChildNode(const Node& node) in order to avoid the slicing of Cube to Node. Commented Nov 15, 2020 at 6:08
  • 1
    Note that just adjusting the signature of addChildNode isn't going to get rid of all the slicing issues this design seems likely to incur. The existence of std::vector<Node> childNodes, for example. It might be worth reconsidering what relationship, exactly, Cubes and Nodes are supposed to have, and why you've chosen inheritance. Commented Nov 15, 2020 at 6:15
  • @NathanPierson has a valid point. Have a look at threads like this: stackoverflow.com/questions/56464702/avoiding-object-slicing Commented Nov 15, 2020 at 6:24
  • As others have said, you can call a method of a parent class from the child exactly as you'd call one of the child's own methods - as long as the parent method has visibility of "public" or "protected". Commented Nov 15, 2020 at 6:31

3 Answers 3

1

No, the parent classes public functions are callable from the child object. However, the prototype of the function is

void Node::addChildNode(Node node);

So it's taking a Node object & not a Cube object. So your compiler cannot find a function which takes a Cube object & hence the error.

The fix is to use a pointer to Node or reference to Node while declaring/defining the function.

So you function should be

void addChildNode(Node & node);

In which case, the Node object can be passed to the function & the compiler will find it.

Even better would be to have

// if you aren't looking to modify the passed object inside addChildNode
void addChildNode(const Node & node); 

The following is fine & hence the function will work

Cube b;   
Node &a = b;

or

Node * pn = &b;
Sign up to request clarification or add additional context in comments.

9 Comments

Should be const Node & node if you wanna replicate the author's intention (which does not include the ability of the function to modify the input object).
@goodvibration - yes, true. I am just giving the simplest possible function prototype which will compile
It's simpler, but it is generally wrong, since changing function addChildNode(Node node) to addChildNode(Node& node) opens up the possibility to fall into a world of hurt. Better give this user a complex correct solution rather than a simple incorrect solution.
Thanks, but my problem is that it says that addChildNode doesn't exist when I do mainCube.addChildNode;
Since Cube publically inherits from Node, that shouldn't be the problem. The mismatch between Node* and Cube, however, would cause code to fail to compile.
|
1

The derived classes should be able to see the addChildNode function if you keep the signature of the function aligns. This is not a big issue. However, there are a few more "serious" issues with your code:

  1. You need to make the base class' destructor virtual to avoid some undefined behaviors.

  2. You have to design the ownership of nodes carefully. I guess you want the Node class to own and manage its children nodes. That means function addChildNode actually takes the ownership of the passed in node object, and it should also be deleted during destruction.

  3. In function addCubes(), there is a loop that keeps calling addChildNode function but passes the local variable Cube c; which will be out of scope and destroyed after the loop. Thus, the parent object mainCube will holds pointers to already destroyed objects, and it will cause a crash.

After fixing all these issues, your code looks like this:

class Node
{
public:
    Node() {};
    virtual ~Node() {
        for(auto n: childNodes) delete n;
    };

    void setParentNode(Node* parent) {this->parentNode = parent;}
    Node* getParentNode() {return this->parentNode;}

    std::vector<Node*> getChildNodes(){return this->childNodes;}

    void addChildNode(Node* node) {
        childNodes.push_back(node);
    };
    void removeNode();

private:
    std::vector<Node*> childNodes;
    Node* parentNode = nullptr;
};

class Cube : public Node
{
public:
    Cube() {};
};

void addCubes(){
    Cube mainCube;
    for(int i = 0; i < 10; i++){
        Cube *c = new Cube();
        mainCube.addChildNode(c);
    }
}

It is preferred to use smart pointers to manage memory, and the code is more elegant and easier to read, and it makes it harder to make mistakes :-).

#include <memory>

class Node
{
public:
    Node() {};
    virtual ~Node() {};

    void setParentNode(Node* parent) {this->parentNode = parent;}
    Node* getParentNode() {return this->parentNode;}

    std::vector<std::shared_ptr<Node>>& getChildNodes(){return this->childNodes;}

    void addChildNode(std::shared_ptr<Node> node) {
        childNodes.push_back(std::move(node));
    };
    void removeNode();

private:
    // childNodes own elements in it, they will be deleted automatically.
    std::vector<std::shared_ptr<Node>> childNodes;
    Node* parentNode = nullptr;
};
class Cube: public Node
{
public:
    Cube() {};
};
void addCubes(){
    Cube mainCube;
    for(int i = 0; i < 10; i++){
        auto c = std::make_unique<Cube>();
        mainCube.addChildNode(std::move(c));
    }
}

Comments

0

Assuming that you have shared the entire implementation of your code. You have not defined the body of the function addChildNode, similar to setParentNode etc. You need to do something like childNodes.push_back(node); inside that function.

Note: It is also necessary that you pass the input to addChildNode as shown in the answer by @user93353. Also, define childNodes as std::vector<Node *> in order to avoid object slicing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.