C , использующий класс внутри класса

#c

#c

Вопрос:

У меня есть основной вопрос, который беспокоил меня некоторое время.

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

пример 1

 #include "ClassA.h"

class ClassB {

   public:
     ClassB();
     ~ClassB();
     ClassA* a;
};
#endif
  

пример 2 Вот другой способ сделать это. Заголовок ClassA будет определен в исходном файле ClassB.

 class ClassA;

class ClassB {

   public:
     ClassB();
     ~ClassB();
     ClassA* a;
};
#endif
  

В чем разница между этими двумя методами?

Комментарии:

1. ex2 — это прямое объявление, и заголовочные файлы были созданы, чтобы по существу избавиться от них в сложных случаях.

Ответ №1:

Полная компоновка компилятора classA известна компилятору, когда вы включаете определение класса.

Второй синтаксис называется прямым объявлением и теперь classA является неполным типом для компилятора.

Для неполного типа
вы можете:

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

Но вы не можете:

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

Таким образом, прямое объявление класса может работать быстрее, потому что компилятору не нужно включать весь код в этот файл заголовка, но это ограничивает то, как вы можете использовать тип, поскольку он становится неполным типом.

Комментарии:

1. Другим важным преимуществом неполных типов является то, что они (могут) улучшить инкапсуляцию, поскольку клиентам B не нужно «перетаскивать» зависимости A.

2. Я думаю, что более быстрая работа — это отвлекающий маневр. В 99% случаев не будет заметного изменения скорости. Речь идет об инкапсуляции. Пользователям B не нужно знать об A.

Ответ №2:

Второй метод позволяет создавать указатели только на ClassA, поскольку его размер неизвестен. Однако он может компилироваться быстрее, поскольку заголовок для полного определения ClassA не включен.

Ответ №3:

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