С++ включает заголовочный файл

Итак, у меня есть проблема, где:

класс A должен знать о классе B, класс B должен знать о C, а класс C должен знать об A. По сути, это круг, поэтому я получаю ошибки определения. Я попробовал предварительное объявление, но то, что сверху, не знает о том, что еще происходит внизу.

Как бы я поступил в такой ситуации?

Спасибо

Дэйвид


person dajee    schedule 10.04.2012    source источник
comment
Вы начинаете с разрыва циклической зависимости. По аналогичному вопросу см. этот ответ SO.   -  person Adam Mihalcin    schedule 10.04.2012
comment
Что вы имеете в виду под тем, что то, что наверху, не знает о том, что еще происходит внизу?   -  person cloudygoose    schedule 10.04.2012
comment
в заголовочном файле скажите, что вы объявляете: класс A, B C в этом порядке. A по-прежнему нужно знать о B или C, но, поскольку он находится сверху, он не может их использовать. Если это имеет смысл.   -  person dajee    schedule 10.04.2012
comment
Разве вы не можете просто объявить класс ..? класс А; класс Б; класс С;   -  person Anerudhan Gopal    schedule 10.04.2012


Ответы (5)


Предполагая, что это что-то простое, приведенный выше комментарий Адама Михальчина верен в том смысле, что на него отвечает аналогичный вопрос. Но я все равно закодирую.

Предполагая, что у вас есть это (определения методов не имеют значения):

class A
{
    B* ptrB;
}

class B
{
    C* ptrC;
}

class C
{
    A* ptrA;
}

Затем вы можете, как сказал Адам, просто перенаправить все 3 из них следующим образом:

class A;
class B;
class C;

И поместите этот блок над всеми тремя из них. Однако здесь важно то, что это когда есть указатели на другие классы, а не композиция, где они являются частью класса. Вы можете использовать прямое объявление, чтобы обеспечить правильную компиляцию при работе с указателями, но не с другими типами данных. Итак, если бы было это:

class D
{
    B myB;
}

Со всем остальным, как указано выше, вам нужно будет иметь «настоящее» определение для B выше «настоящего» определения для D. Но остальное может быть таким же. Форвардное объявление «работает» только для указателей.

Однако вы ДОЛЖНЫ разорвать цикл зависимости где-нибудь с помощью указателя. Если указателя никогда нет, то структура данных «бесконечна» и, следовательно, не работает. Это потому, что в моем примере D всегда содержит B. Но что, если A всегда содержит B, B всегда содержит C, а C всегда содержит A? Ну, этому финальному А нужен еще один Б, которому нужен еще один В, который... Надеюсь, вы уловили идею. Но с указателями вы можете зациклить это. С композицией (не указателями) он не может зацикливаться.

person Kevin Anderson    schedule 10.04.2012

Если классы тесно связаны, то можно обойтись

  • Объявите классы без реализации методов, возможно, используя предварительные объявления, затем реализуйте методы (возможно, в файле реализации).

В противном случае вы можете

  • Выделите более абстрактные интерфейсы, достаточные для того, чтобы классы работали, не зная полной информации друг о друге.

Но, скорее всего, у вас есть ошибка на уровне дизайна, и если это так, просто исправьте это.

person Cheers and hth. - Alf    schedule 10.04.2012

Что вы можете сделать, так это объявить класс A в заголовочном файле для класса C, а затем в файле .cpp включить заголовок для класса A.

Для справки о том, как пересылать объявления класса A, взгляните на эту ссылку — Переадресовать объявления в С++

person josephthomas    schedule 10.04.2012

скорее всего, у вас просто ошибка на уровне дизайна.

Однако, если вам нужно сделать это, например, просто попробуйте использовать прямое объявление, объявив пустой класс A, B без представления какой-либо подробной реализации в заголовочном файле C. затем включите заголовки A и B в файл реализации C, когда вам нужно их использовать.

Помните, что вы можете использовать указатель только в объявлении класса C.

person House.Lee    schedule 10.04.2012

В ваших заголовочных файлах используйте следующую конструкцию:

#ifndef MYCLASS_HPP__20120410__0747
#define MYCLASS_HPP__20120410__0747
// Your definions of class, struct, etc...
#endif//

И все включенные файлы (кроме самого Myclass.hpp) должны находиться в заголовочном файле класса Myclass.hpp. Он должен быть включен в файл Myclass.cpp.

person fat_lor_troll    schedule 10.04.2012