LINUX.ORG.RU

Circular dependency или как это назвать

 


0

1

Привет всем! И так. У меня есть два заголовочных файла: Basic.h и Compile.h.

В Basic.h используется класс из Complie.h и есть #include «Complie.h», а в Complie.h наоборот - используется класс из Basic.h и есть #include «Basic.h». Ну и из-за этого возникают ошибки:

Compiler.hpp:91:3: error: ‘Basic’ does not name a type

И т.д. Как лучше сделать, что бы компилировало?


Один знакомый телепат предположил что-то типа такого.

metar ★★★
()
Ответ на: комментарий от numas13
#ifndef __MOBILEBASIC_BASIC_HPP
#define __MOBILEBASIC_BASIC_HPP
...........................
#include "Compiler.hpp"

........................

class Basic {
	public: 
		.................
		Compiler *compiler_instance; 
		..................
		Basic() {
			.................
		}
		
		inline Compiler *getCompiler() {
			 if (compiler_instance == NULL) 
				compiler_instance = new Compiler(this); 
			return compiler_instance; 
		}
		
		~Basic() {
			if (compiler_instance) {
				delete compiler_instance; 
				compiler_instance = NULL; 
			}
		}
}; 
}; 
#endif
#pragma once
#ifndef __MOBILEBASIC_COMPILER_HPP
#define __MOBILEBASIC_COMPILER_HPP
............
#include "Basic.hpp"
..................
using namespace std; 
namespace MobileBasic {
............
class Compiler {
	public:
		................
		Basic *basic; 
		...................
		Compiler(Basic *b) {
			..................
			basic = b; 
		}
		
		inline void setCompiler(Basic *b) { basic = b; }
		.....................
	}; 
}; 
#endif 

Azq2
() автор топика

Я так понимаю, есть два класса, и хочется связать их друг с другом. Так вот: только один класс может видеть полное определение другого, наоборот — нельзя (исключением является случай, когда оба класса вложены в третий класс, но это неудобно). Вместо этого используют другие подходы:

  • Убирается требование видеть определение другого класса: Basic.h включается только в Compile.cpp, а Compile.h только в Basic.cpp.
  • Даётся объявление класса вместо определения
    class Texture2D;
    
    class Sprite
    {
    // Здесь можно работать с указателями и ссылками на Texture2D.
    };
    
  • Из какого-то класса выделяется интерфейс и используется в другом класса, да и вообще паттерны помогают в таких ситуациях.
quiet_readonly ★★★★
()
Последнее исправление: quiet_readonly (всего исправлений: 1)
Ответ на: комментарий от Azq2

вынеси inline методы из Basic в .cpp файл, добавь forward declaraion как написал анонимус.

alex_custov ★★★★★
()
Ответ на: комментарий от quiet_readonly

Угу, понял уже. Спасибо)

Azq2
() автор топика

Я бы посоветовал пересмотреть архитектуру приложения, если у вас есть необходимость сабжа.

Вот зачем, например, у Compiler есть поле Basic* и к тому же публичное?

Зачем были эти классы разделены, если у них такая жесткая да еще и двухсторонняя связь?

grondek
()
Ответ на: комментарий от grondek

Я бы посоветовал пересмотреть архитектуру приложения, если у вас есть необходимость сабжа.

Сложнее калькулятора что-нибудь писал?

anonymous
()

Почитайте, что такое forward declaration.

// file compile.h

class basic;

class compile
{
   basic* m_basic;
};
// file basic.h

class compile;

class basic
{
   compile* m_compile;
};
andreyu ★★★★★
()
Ответ на: комментарий от grondek

Я бы посоветовал пересмотреть архитектуру приложения, если у вас есть необходимость сабжа.

class Foo {
    Bar *child;
};
class Bar {
    Foo *parent;
};

не?

Stil ★★★★★
()
Ответ на: комментарий от Stil

На мой взгляд Bar*child и Foo*parent лучше спрятать в приватные классы и не светить в описании Bar и Foo. Тогда и с зависимостями в заголовочных файлах будет попроще.

grondek
()

А по сабжу, если вы делаете 2 зависимых класса, хотя и можно их писать в разных заголовочниках, но лучше так не делать. А если ради воплощения каких-то непонятных сферичных коней приспичило писать в разных заголовочниках, то один из инклюдов - лишний. В любом случае, перед классом идущим по тексту программы первым, независимо от того, инклюдом он включён или напрямую написан, должно стоять объявление всех классов, которые он использует, например, так:

class Second;

class First {
    Second *something;
};
class Second {
    First *anything;
};
next_time ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.