Circular Dependencies

Hi,

this is kind of a spin off of my last post (http://www.cplusplus.com/forum/beginner/120329/).

I have some weird include problems, it potbelly has to do with circular dependencies. its just i don't understand why its wrong, let alone know what\how to fix this problem.

Note:
if i comment out the ConvertToPoint functions it builds fine

the sample code :

PointF.h:
1
2
3
4
5
6
7
8
9
#pragma once
class PointF
{
public:
	float X, Y = 0;

	PointF(float X = 0, float Y = 0);
	PointI ConvertToPointI();
};


PointF.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "PointF.h"
#include "PointI.h"

PointF::PointF(float X, float Y)
{

}

PointI PointF::ConvertToPointI()
{
	PointI i;
	return i;
}


PointI.h:
1
2
3
4
5
6
7
8
9
#pragma once
class PointI
{
public:
	int X, Y = 0;

	PointI(int X = 0, int Y = 0);
	PointF ConvertToPointF();
};


PointI.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "PointI.h"
#include "PointF.h"

PointI::PointI(int X, int Y)
{

}

PointF PointI::ConvertToPointF()
{
	PointF f;
	return f;
}


Main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
#include "PointF.h"
#include "PointI.h"

int main()
{
	PointF f;
	f.X = 1.265f;
	f.Y = 1.5468f;

	PointI i;
	i = f.ConvertToPointI();
}


so now for the errors:

1>------ Build started: Project: IncludeTest, Configuration: Debug Win32 ------
1> PointI.cpp
1>...\pointi.h(8): error C2146: syntax error : missing ';' before identifier 'ConvertToPointF'
1>...\pointi.h(8): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>...\pointi.h(8): warning C4183: 'ConvertToPointF': missing return type; assumed to be a member function returning 'int'
1>...\pointi.cpp(10): error C2556: 'PointF PointI::ConvertToPointF(void)' : overloaded function differs only by return type from 'int PointI::ConvertToPointF(void)'
1> ...\pointi.h(8) : see declaration of 'PointI::ConvertToPointF'
1>...\pointi.cpp(10): error C2371: 'PointI::ConvertToPointF' : redefinition; different basic types
1> ...\pointi.h(8) : see declaration of 'PointI::ConvertToPointF'
1> PointF.cpp
1>...\pointf.h(8): error C2146: syntax error : missing ';' before identifier 'ConvertToPointI'
1>...\pointf.h(8): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>...\pointf.h(8): warning C4183: 'ConvertToPointI': missing return type; assumed to be a member function returning 'int'
1>...\pointf.cpp(10): error C2556: 'PointI PointF::ConvertToPointI(void)' : overloaded function differs only by return type from 'int PointF::ConvertToPointI(void)'
1> ...\pointf.h(8) : see declaration of 'PointF::ConvertToPointI'
1>...\pointf.cpp(10): error C2371: 'PointF::ConvertToPointI' : redefinition; different basic types
1> ...\pointf.h(8) : see declaration of 'PointF::ConvertToPointI'
1> Generating Code...
1> Compiling...
1> Main.cpp
1>...\pointf.h(8): error C2146: syntax error : missing ';' before identifier 'ConvertToPointI'
1>...\pointf.h(8): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>...\pointf.h(8): warning C4183: 'ConvertToPointI': missing return type; assumed to be a member function returning 'int'
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Last edited on
You're right that the issue is a circular dependency. You're probably better off building a separate class of static functions or set of global functions in a separate file that do the conversions.
Basically, in order for PointI to compile it needs to know the size of PointF. When it tries to figure this out, it sees that it needs to know the size of PointI. Thus you get into a circular dependency.

The solution is to pass references ( or pointers ) instead of the whole object. The compiler knows the size of these things.

This means that you would have to return a reference from the Convert functions, but you probably don't want to do this because it you will need to allocate dynamically, and then have to deal with memory.

I would suggest you make it so the Points can be constructed with the other:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// PointI.h

// Guards assumed

// forward delcare PointF so the compiler knows it exists.
// you can't use the class, only it's name, and only references/pointers
// FloatF will be an incomplete type
class FloatF;

class FloatI
{
	public:
	// Construct a FloatI with reference of FloatF
	FloatI( const FloatF& );
};
1
2
3
4
5
6
7
8
9
10
11
// PointI.cpp

#include "PointI.h"

// Now you can include PointF.h so that it is a complete type
#include "PointF.h"

FloatI::FloatI( const FloatF& floater )
{
	// do things with floater
}
1
2
3
4
5
6
7
8
9
10
// Same for FloatF
// FloatF.h

class FloatI;

class FloatF
{
	public:
	FloatF( const FloatI& );
};
1
2
3
4
5
6
7
8
// FloatF.cpp
#include "FloatF.h"
#include "FloatI.h"

FloatF::FloatF( const FloatI& integral )
{
	// do things with integral
}
Last edited on
Lowest0ne: to be honest i started off doing it with the constructor but that did not work so i tried with function.

to be honest i did not know you could do this.
1
2
3
4
// forward delcare PointF so the compiler knows it exists.
// you can't use the class, only it's name, and only references/pointers
// FloatF will be an incomplete type
class FloatF;

Thank you so much!
Topic archived. No new replies allowed.