Как я могу получить доступ к дочернему классу, который хранится в родительском классе? - PullRequest
0 голосов
/ 07 июня 2019

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

Я «погуглил» мою проблему, и я понял, что были некоторые проблемы с приведением типов.Я попробовал и не работал.

Пример кода:

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';
}

Это ошибка, которую я получаю:

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

Ответы [ 2 ]

3 голосов
/ 07 июня 2019

root - указатель узла. root->right - это другой указатель узла. root->right->down - это, как вы уже догадались, указатель на узел.

Когда вы делаете [...]->value, вы разыменовываете этот указатель Node, который дает вам Node, а затем пытаетесь получить член value на нем. Но Node не имеет value члена!

Вы можете попытаться преобразовать указатель Node в указатель ENode, используя динамическое приведение. Который будет выглядеть так:

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;
}

Но для этого вам нужно сделать Node полиморфным (что вы можете увидеть детально здесь ).

Также обратите внимание, что в рабочем коде вы должны проверить, чтобы убедиться, что root, root->right и root->right->down не равны NULL, прежде чем идти дальше и разыменовывать их.

1 голос
/ 07 июня 2019

Корневой класс Node имеет только указатели на другие Node, поскольку он не знает, какими производными классами они могут быть.

"Обычно" лучше иметь правильный интерфейс в базовом классе, чтобы получать результаты / значения из производных классов различного вида.

Например, если у вас есть животное базового класса:

class animal
{
    virtual int number_of_limbs() = 0;
}

Тогда производный класс свиньи:

class pig: public animal
{
   int number_of_limbs() override { return 3;}
}

При этом «интерфейс» к классу является общим, но у каждого производного / специализации может быть определенное значение.

В вашем случае вам, вероятно, просто нужна функция с именем virtual int get_value() в вашем базовом классе, а затем реализовать ее в вашем ENode классе ...

(обратите внимание, что весь код выше только псевдокод)

...