2010-09-27 3 views
1

У меня есть два класса, которые зависят друг от друга. Я решил эту проблему раньше, но я не могу за всю жизнь помнить, как это исправить. Мой упрощенный код:Как разрешить зависимые классы?

struct MenuOption{ 
    string Text; 
    int Choice; 
    bool UseSubMenu; 
    Menu SubMenu; 
}; 

class Menu{ 
public: 
    Menu(MenuOption optionlist[],int optioncount); 
}; 

ответ

3
  • Используйте передовые декларации

Ie:

// Forward declaration to assure A of B's existence. 
class B; 

class A { // uses B 
    B* b; 
}; 

class B { // uses A 
    A* a; 
}; 
  • Использовать указатели и не экземпляры объекта: потому что компилятор должен знать, сколько места выделить членам класса , Таким образом, наличие экземпляра объекта не будет работать, потому что компилятор не знает его размер, не видя полного объявления своего класса. Однако указатели имеют одинаковый размер, который известен компилятору, не глядя на что-либо дополнительное.
+0

Ах. В этом есть смысл. Я полностью забыл о рекурсивной бесконечной размерной структуре, которая создала бы. – Earlz

0

Вам нужно использовать указатели вместо объектов. Я считаю, в этом случае SubMenu должен быть Menu*

EDIT

На самом деле, как другие упомянутые вперед декларации также необходимо. Но с помощью прямых объявлений вы можете просто определить указатель/ссылку, но вы не можете создать объект. Когда вы пытаетесь создать объект, компилятор должен знать, что такое sizeof объекта, который недоступен (даже если вы отправляете объявление вперед). С помощью прямого объявления вы сообщаете компилятору, что Menu имеет тип class, и вы рисуете указатель на объект типа Menu. Подумайте об этом, имея экземпляр один в другой, будет бесконечным возвратом.

+0

Я не понимаю, почему в этом случае мне нужно будет использовать указатели. Позаботьтесь об этом? Не достаточно ли объявление объявления? (кроме того, что мой класс на самом деле не «научил» указателям) – Earlz

+0

Когда структура определена, компилятор должен знать размер структуры. Когда выполняется прямое объявление, он сообщает компилятору, что класс существует, но не его размер. Это означает, что когда компилятор пытается определить размер MenuOption, он не может его вывести, потому что он не знает, что размер меню и размера меню определяется только * после * MenuOption. Но если это указатель на класс, компилятору не нужно знать размер класса, потому что это просто указатель, а указатели имеют фиксированный размер (в зависимости от архитектуры процессора). –

0
class Menu; 
struct MenuOption{ 
    string Text; 
    int Choice; 
    bool UseSubMenu; 
    Menu* SubMenu; 
}; 

class Menu{ 
public: 
    Menu(MenuOption optionlist[],int optioncount); 
}; 

В принципе, вы «вперед объявить» класса Menu, а затем использовать указатель на меню в подменю.

1

Используйте передовые декларации

struct MenuOption; 

class Menu{ 
public: 
    Menu(MenuOption optionlist[],int optioncount); 
}; 

struct MenuOption { 
    string Text; 
    int Choice; 
    bool UseSubMenu; 
    Menu SubMenu; 
}; 

Вам не нужно делать какие-либо элемент данных указатель. В приведенном выше фрагменте кода нет «рекурсивного бесконечного размера».

Независимо от этого, по-прежнему представляется хорошей идеей сделать это SubMenu указателем. Потому что, похоже, не требуется подменю, не так ли? Поэтому вы должны использовать указатель, поскольку в противном случае член будет всегда быть меню и должен быть инициализирован. Указатель можно оставить неинициализированным или как нулевой указатель. Вы также можете использовать boost::optional<> вместо

struct MenuOption { 
    string Text; 
    int Choice; 
    boost::optional<Menu> SubMenu; 
};