2014-11-26 1 views
3

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

У меня есть три класса А, В и InterfaceA

Defintion InterfaceA

#ifndef INTERFACE_A_H 
#define INTERFACE_A_H 
#include "B.h" 

namespace Example 
{ 
    class B; // Forward declaration? 
    class InterfaceA 
    { 
    Example::B test; 

    }; 

} 

#endif 

Definiton класс А

#ifndef A_H 
#define A_H 
#include "InterfaceA.h" 
namespace Example 
{ 
    class A : public Example::InterfaceA 
    { 

    }; 
} 
#endif 

класс Defintion Б

#ifndef B_H 
#define B_H 
#include "A.h" 

namespace Example 
{ 
    class A; // Forward declaration? 
    class B 
    { 
    Example::A test; 
    }; 

} 

#endif 

Основной

#include "A.h" 
#include "B.h" 
int main() 
{ 
    Example::A a; 
    Example::B b; 
} 

Я получаю следующее сообщение об ошибке в визуальной студии:

'Example :: B :: тест' использует неопределенный класс 'Пример :: A'

Edit: Спасибо до сих пор, за всякую помощь. Это было очень полезно. Я думаю, моя проблема в том, что у меня был очень плохой дизайн в моем реальном проекте. Я изменю это.

Помимо этого у меня сейчас лучше понять для опережающего описания :-)

+1

Поскольку оба класса 'A' ​​и' B' ссылаются друг на друга * по значению *, нечего делать, кроме как редизайна или путем создания одной (или обеих) ссылок или указателей. –

+1

Если 'A' содержит' B', то 'B' не может содержать' A'. Одна или другая переменная 'test' должна быть указателем или ссылкой, и в этом случае этот тип должен быть объявлен, а не определен. –

ответ

4

Вы создаете циклическую зависимость. Пересмотрите свой дизайн.

Вам действительно нужен экземпляр класса A внутри B и B внутри A?

3

Если вам действительно нужно, что ссылки на класс А класс В, и наоборот, вместо того, чтобы иметь экземпляры А и В в качестве элементов данных, следует использовать указатели , например, что-то вроде этого:

// A.h 

#pragma once 

#include <memory> // for std::unique_ptr 

// Forward declaration (A references B using pointer) 
class B; 

class A 
{ 
... 
    std::unique_ptr<B> m_pB; 
}; 

И точно так же:

// B.h 

#pragma once 

#include <memory> // for std::unique_ptr 

// Forward declaration (B references A using pointer) 
class A 

class B 
{ 
... 
    std::unique_ptr<A> m_pA; 
}; 

PS
не связана с ядром вашего вопроса, однако обратите внимание, что я использовал #pragma once вместо "старого стиля" #ifndef/#define/#endif включают охранников; #pragma once кажется мне проще и понятнее.

+0

Но '#pragma once' является нестандартным –

+0

@BasileStarynkevitch: Я думаю, что' #pragma once' поддерживается самыми важными и распространенными компиляторами C++: GCC, Clang и MSVC. В любом случае, если это нестандартно, я бы предложил комитету C++ стандартизировать его. –

+0

В настоящее время я работаю над проектом на базе микроконтроллера. Я использую C и C++. Вот почему я не могу использовать #pragma один раз. В любом случае, я думаю, что # прагма должна стать стандартом. –