2013-09-26 3 views
2

Прошло много времени с тех пор, как я сделал какое-либо программирование на C++, и я был бы очень признателен, если бы кто-нибудь мог помочь мне создать класс Node, у которого есть одна из его частной переменной список (или вектор) объектов класса Node ,Для данного класса в C++ возможно ли иметь в качестве частной переменной вектор объектов одного класса?

Я надеюсь создать классовую структуру как таковую:

class Node { 
private: 
    string ID; 
    vector <Node> list; 
public: 
    Node(); 
    void some_Function(); 
}; 

Является ли это правильный подход? Возможно ли, чтобы класс имел один из своих частных членов как список объектов одного и того же типа класса?

+1

Что вы можете иметь, это «вектор ». – ChronoTrigger

+0

'std :: vector >' или 'std :: vector >' еще лучше. – aschepler

ответ

8

Нет, вы не можете.

Когда вы определяете объект типа vector<T>, T должен быть полным типом, который не должен быть до конца определения класса.

Некоторые компиляторы будут принимать код в любом случае (они будут принимать вектор некоторого неполного типа), но он не допускается стандартом C++.

+0

У нас есть 'vector ' как указано в комментариях? – Saksham

+2

@Saksham: Да - 'Node *' - полный тип, даже если 'Node' не является. –

+0

О, да. теперь я понимаю, что знаю это. – Saksham

0

Да, вы можете, либо с помощью указателей или вводя вспомогательный класс:

class NodeVector; 

class Node { 
    private: 
    string ID; 
    NodeVector *vect; 

    public: 
    Node() : vect(new NodeVector) { } 
    // Don't forget other constructors & destructor because you allocate vect 
}; 

class NodeVector { 
    public: 
    std::list<Node>; 
}; 
+0

В вашем примере указатель * и * вводит вспомогательный класс. Итак, в чем смысл вспомогательного класса? –

+0

Во-первых, альтернативой будет выделение указателя на каждый узел отдельно, что является N-распределением для N "других" узлов. Если вы замените список на вектор в этом примере, у вас будет непрерывный кусок памяти для всех «других» узлов. Во-вторых, явное выделение здесь происходит только в конструкторах и освобождении в деструкторе один раз за время жизни «этого» узла, а не каждый раз, когда меняется список «других» узлов, поэтому меньше шансов на ошибку. Наконец, это обеспечивает достойную часть функциональности Node, а именно отслеживание «других» узлов в отдельный класс, который хорош для дизайна. – Michael

0

Так же, как сказал Джерри. Ты не можешь.

Это не то же самое, как

class node { 
    int data; 
    node *next; 
} 

с узлом *, компилятор должен знать размер указателя только. Но для vector<T> компилятор должен знать размер вашего класса T, который не определен до конца определения класса.

+0

Жаль, Джерри.Я не могу добавить свои комментарии к вашему ответу, так как моя репутация слишком низкая. Таким образом, отдельный ответ. – qxixp

2

Вы не можете сделать это непосредственно в одном классе. Но вы можете использовать CRTP, что специально предназначено для чего-то подобного.

У вас будет базовый класс шаблона и производный класс, который является шаблоном на его собственном типе. Базовый класс затем может свободно определять другие дженерики (например, vector) на основе производного класса. Пример кода ниже:

#include <vector> 
using namespace std; 

template <typename Derived> 
class Base{ 
    vector<Derived> nodes; 
public: 
    void TestInsert(const Derived& der){ 
     nodes.push_back(der); 
    } 
    void TestPrintSize(){ 
     printf("NUM %d\n", nodes.size()); 
    } 
}; 

class Derived1 : public Base<Derived1>{}; 

int main(){ 
    Derived1 der1, der2; 
    der2.TestInsert(der1); 
    der2.TestPrintSize(); 
} 
+0

Это красивое решение CRTP –

Смежные вопросы