2011-02-04 2 views
1

Я новичок в программировании на С ++, так что, возможно, вы найдете мой вопрос слишком глупым. К сожалению об этом, но я хотел бы знать, как реализовать эту структуру Java-стиль:Как реализовать классы со ссылками друг на друга?

#include "B"; 
class A { 
    B objB; 
} 
--- 
#include "A"; 
class B { 
    A objA; 
} 

компилятор сходит с ума, пытаясь понять этот код. Не могли бы вы посоветовать мне о возможном решении? Благодаря!

ответ

5

Этот код является незаконным в C++ и компилятор право отклонить его. Проблема в том, что если у вас есть конкретный объект типа A внутри объекта типа B и наоборот, то нет значимого определения размера любого объекта. В частности, объекты в C++ должны иметь по крайней мере один байт. Поэтому, если задан объект типа A (назовите его a), должен быть один байт хранилища для a, a.objB.objA, a.objB.objA.objB.objA и т. Д. На самом деле вам понадобится бесконечное пространство для хранения, потому что всегда есть объект, вложенный внутри внутри эти объекты!

Чтобы исправить это, вы захотите изменить это так, чтобы вы сохраняли указатели объектам типа B и A в A и B соответственно. Это разрушает цепочку, поскольку в то время как указатель A*указывает на объект A, сам указатель не является объектом A и поэтому использует только четыре байта. После этого вы можете использовать форвардные объявления для объявления этих указателей. Например:

Файл: хиджры:

class B; 
class A { 
    B* objB; 
}; 

Файла: B.h:

class A; 
class B { 
    A* objA; 
}; 

Надеется, что это помогает!

+0

благодарит за ваше объяснение. это было действительно полезно для понимания. – Kid24

+0

@ Kid24- Рад помочь! Не забудьте принять ответ, если вы думаете, что он отвечает на ваш вопрос.:-) – templatetypedef

1

Вы не можете создать объект B внутри объекта A, который сам находится внутри объекта B. Рекурсивно вы никогда не сможете построить объект, потому что он имеет бесконечную рекурсию.

Что вы можете сделать:

#include "B" 
class A { 
    B *objB; 
} 

#include "A" 
class B { 
    A objA 
} 
+0

Это не будет работать, если заголовки правильно окружены включенными охранниками. – GManNickG

+0

@GMan: Конечно. И, возможно, объявление прямого класса в каждом из включенных файлов. – Benoit

2

Вам необходимо переслать-объявить

class B; 

, прежде чем определить класс А, то, как и прежде. Это будет работать для ссылок, но не для таких объектов, поскольку вы не можете действительно иметь объект, неявно содержащий себя.

+0

Предварительная декларация помогла! благодаря! – Kid24

0

Другой способ увидеть это - рассмотреть один исходный файл, включив A.H или B.H "first". ["first" цитируется с учетом вероятной путаницы там.]

class A { 
    B objB; 
} 
class B { 
    A objA; 
} 

Как это может быть понято? Мы не можем определить А до того, как будем знать B, и мы не можем определить B до того, как будем знать A. Следовательно, решение по косвенности, как отмечалось другими.

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