Search code examples
c++pointerssparse-matrix

How can I access a child class member stored in a parent class?


I was assigned to create a sparse matrix. In the process, I got into a problem. I realized I could not access a member of a child class that was stored in a parent class.

I 'googled' my problem and what I got was that there were some casting problems. I tried it out and did not work either.

Sample code:

main.cpp

#include <iostream>

template <typename T>
class Node
{
public:                     // public for example purposes
    Node<T> *down, *right;

public:
    explicit Node(Node<T> *d, Node<T> *r) : down(d), right(r) {}
};

template <typename T>
class HNode : public Node<T>
{
private:
    unsigned idxValue;

public:
    HNode(unsigned iv) : idxValue(iv), Node<T>(nullptr, nullptr) {}
};

template <typename T>
class ENode : public Node<T>
{
public:                     // public for example purposes
    unsigned row;
    unsigned col;
    int value;

public:
    ENode(unsigned r, unsigned c, int v) : row(r), col(c), value(v), Node<T>(nullptr, nullptr)
    {}
};

int main(void)
{
    Node<int> *root;

    root = new Node<int>(nullptr, nullptr);

    root->right = new HNode<int>(0);
    root->down = new HNode<int>(0);
    root->right->down = new ENode<int>(0, 0, 10);


    std::cout << root->right->down->value << '\n';
}

This is the error I get:

error: no member named 'value' in 'Node<int>'
std::cout << root->right->down->value << '\n';

Solution

  • root is a Node pointer. root->right is another Node pointer. root->right->down is--you guessed it--a Node pointer.

    When you do [...]->value, you're dereferencing that Node pointer, which gives you a Node, and then trying to get the value member on it. But Node has no value member!

    You could attempt to cast your Node pointer into an ENode pointer, using dynamic cast. Which would look like:

    Node *n = root->right->down;
    if(ENode *en = dynamic_cast<ENode*>(n)) {
        std::cout << en->value << std::endl;
    } else {
        std::cout << "That's not an ENode!" << std::endl;
    }
    

    But to do this, you'll need to make Node polymorphic (which you can see detailed here).

    Also note that in production code, you should be checking to make sure root, root->right and root->right->down are all non-null before going ahead and dereferencing them.