Как лучше всего работать с классами C ++, которые должны иметь объект собственного типа? - PullRequest
0 голосов
/ 24 апреля 2020

Я новичок в C ++ с некоторым опытом в других языках программирования (например, Python, Javascript). У меня есть пара вопросов, касающихся "рекурсивных" классов - классов, которые объявлены внутри себя - в C ++.

Вопрос 1

Для класса с конструктором я понимаю, что объявляя его внутри себя, приведет к тому, что его объявление будет неполным, и, следовательно, компилятор не сможет определить размер своих объектов. До сих пор я узнал, что объявление класса может содержать только указатель на тип self или stati c объект типа self . Тем не менее, я не понимаю, какие преимущества в любом из этих подходов? Моя цель - использовать класс, очень похожий на древовидную структуру / сеть, где каждый узел хранит свой родительский узел и дочерние узлы!

Вопрос 2

И родительские, и дочерние узлы будут установлены с помощью функций класса. Как мне объявить собственные типы в функции того же класса? Я также использую stati c или указатели? Как правильно инициализировать в этом случае?

пример. cpp

#include "Point.hpp"

class Node {
    //Node parent; // ERROR

    // Option 1: Pointer
    Node * parent;

    // Option 2: Static
    static Node parent;

    vector<Node> children;

public:
    Node(float _x, float _y, float _z);
    void setChildren(/* some params */);

    float x, y, z;
};

example.hpp

Node::Node(float _x, float _y, float _z) {
    x = _x;
    y = _y;
    z = _z;
}

void Node::setChildren(/* some params */) {
    Node child1, child2; // ERROR: how to declare here?

    // do stuff with the parameters...

    child1 = {/*x1, y1, z1*/}; // ERROR: how to initialise?
    child2 = {/*x2, y2, z2*/}; // ERROR: how to initialise?
    children.push_back(child1);
    children.push_back(child2)

Надеюсь, кто-нибудь сможет мне это объяснить! Я действительно потерян здесь.

Спасибо! Любая помощь с благодарностью.

1 Ответ

2 голосов
/ 24 апреля 2020

Ваше заявление и определение неверны. Определение класса должно быть в заголовочном файле (.hpp), а объявления функции / конструктора et c должны быть в исходном файле (. cpp). Вам нужно будет включить заголовочный файл в исходный файл следующим образом:

example.hpp

#include "Point.hpp"

class Node {
    // Use Option 1: Pointer
    Node* parent = nullptr;

    list<Node> children;

public:
    Node(float _x, float _y, float _z);
    void setChildren(/* some params */);

    float x, y, z;
};

пример. cpp

#include "example.hpp"

Node::Node(float _x, float _y, float _z) {
    x = _x;
    y = _y;
    z = _z;
}

void Node::setChildren(/* some params */) {
    Node child1 = {x1, y1, z1};
    Node child2 = {x2, y2, z2};

    // do stuff with the parameters...

    push_back(child1);
    push_back(child2);
}

Один способ установить родительский указатель, чтобы добавить новую функцию push_back в класс Node, чтобы установить указатель на новый дочерний объект до / или после добавления его в список children.

Также вы инициализируете child1 / 2, как это в C ++.

Node child1 = {x1, y1, z1};
Node child2 = {x2, y2, z2};

«Тем не менее, я не понимаю, какие преимущества дает любой из этих подходов?»

В C ++ у вас есть указатель this на всегда в ваших функциях-членах, что означает, что вам не нужен указатель self, как вы это делаете на других языках программирования this - это ваш указатель self.

Также Если вы планируете то, что я вижу, что вы планируют, для того, чтобы это работало, вы не захотите использовать vector для children, так как vector использует непрерывную память, это сделает недействительными все указатели / итераторы для него, как только внутренняя память для vector изменяется (может произойти на push_back и других операциях) т.е. стереть / вставить). В этом случае проще было бы использовать list вместо vector. Таким образом, родительские обратные указатели не станут недействительными, когда новый дочерний элемент будет добавлен / удален (например, с push_back).

См. Документацию по std :: vector и std :: list.

https://en.cppreference.com/w/cpp/container/vector https://en.cppreference.com/w/cpp/container/list

...