Classes and header files

closed account (ETAkoG1T)

1
2
3
4
5
6
7
8
9
10
// header1.h
class a {
public:
void func(b* item);
}
// header2.h
class b {
public:
void func(a* item);
}

I want to be able to use the a class in class b, and the b class in class a.
How can I make this work?
Last edited on
Declare class b as forward.
You will also need to change line 4 to a pointer since a complete type is required.

1
2
3
4
5
6
// header1.h
class b;
class a {
public:
func(b * item);
}
closed account (ETAkoG1T)
What if I need to use a class that is derived from a in class b?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// header1.h
class b;
class a {
public:
    void func(b* item);
}
class c : public a {
    void Execute();
}
// header2.h

// Add what here?
class b {
public:
    void func(c* item)
   {
        item->Execute();
   }
}


Last edited on
Between lines 1 and 2, just add class b;, it won't affect the rest of your code except to make line 4 compile.
closed account (ETAkoG1T)
I updated it, but that doesn't really matter anymore since AbstractionAnon already told me that. Now I want to do it with inherited classes.
I don't really understand your question, what problem are you having with that code?
closed account (ETAkoG1T)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef HEADER2_H_
#define HEADER2_H_

#include "header1.h"

class a;
class c;

class b {
public:
    void func(c* item)
   {
        item->Execute();
   }
};

#endif 


use of undefined type 'c'

Last edited on
Why would you declare a type and then not define it?
What's in header1.h?
Last edited on
Before you said that the definitions of a and c are in header1.h, but now you instead forward declare them and you show a compiler error about them not being defined? You're really not making sense now. You sure header1.h does NOT include header2.h?
Last edited on
closed account (ETAkoG1T)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef HEADER1_H_
#define HEADER1_H_

#include "header2.h"
#include <iostream>

class b;
class a {
public:
    void func(b* item);
};

class c : public a {
public:
	void Execute() { std::cout << "Hello World"; }
};

#endif 
You need to remove line 4.
closed account (ETAkoG1T)
I just want to find out how I can tell the compiler that c is in header.1 so header.2 can use class c.
I don't know what makes you think it would be unintuitive.


1
2
3
4
5
6
7
8
9
10
#ifndef _HEADER1_H_
#define _HEADER1_H_

class a {
public :
	a() {}
	void method() {/*...*/}
};

#endif 


1
2
3
4
5
6
7
8
9
10
11
#ifndef _HEADER2_H_
#define _HEADER2_H_

#include "header1.h"

class b {
public :
	b() {}
	void method() {a object; object.method();}
};
#endif 
Last edited on
closed account (ETAkoG1T)
Am I thinking wrong? This is supposed to be a finite state machine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef MINER_H_
#define MINER_H_
#include "States.h"


class Miner
{
	State * CurrentState;
	int GoldCarried;
	int GoldInBank;
public:
	Miner() { CurrentState = Sleeping().instance(); }

	void update() 
	{
		if (CurrentState)
		{
			CurrentState->Execute(this);
		}
	}

	void ChangeState(State * NewState) {
		if (CurrentState && NewState)
		{
			CurrentState->Exit(this);
			CurrentState = NewState;
			CurrentState->Enter(this);
		}
	}

};

#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#ifndef STATES_H_
#define STATES_H_

#include "Miner.h"
#include <iostream>
using namespace std;

class State
{
public:
	virtual ~State(){ };

	virtual void Enter(Miner* n)=0;

	virtual void Execute(Miner* n)=0;

	virtual void Exit(Miner* n)=0;
};


class Sleeping : public State
{
public:
	Sleeping() { };
	virtual void Enter(Miner* Unit) 
	{
		cout << "Going to sleep...\n";
	}
	virtual void Execute(Miner* Unit);

	virtual void Exit(Miner* Unit)
	{
		cout << "!What was that?!";
	}
	Sleeping * instance() { 
		static Sleeping sleep;
		return &sleep;
	}
};

class Working : public State
{
public:
	Working() { };
	virtual void Enter(Miner* Unit)
	{
		cout << "Looking forward to working\n";
	}
	virtual void Execute(Miner* Unit)
	{
		cout << "Working is making me tired\n";
		static int Work;
		Work++;
		if ( Work > 4 )
		{
			Work = 0;
			Unit->ChangeState(Sleeping().instance());
		}
	}

	virtual void Exit(Miner* Unit)
	{
		cout << "I'm exhausted\n";
	}

	Working * instance() 
	{
		static Working work;
		return &work;
	}
};


#endif 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "States.h"
#include "Miner.h"


void Sleeping::Execute(Miner* Unit) 
{
		cout << "ZZZZzzzZZZ...\n";
		static int sleepCounter;
		sleepCounter++;
		if ( sleepCounter > 2 )
		{
			sleepCounter = 0;
			Unit->ChangeState(Working().instance());
		}
}

void Working::Execute(Miner* Unit) 

{
		cout << "Working is making me tired\n";
		static int Work;
		Work++;
		if ( Work > 4 )
		{
			Work = 0;
			Unit->ChangeState(Sleeping().instance());
		}
	}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "States.h"
#include "Miner.h"


void Sleeping::Execute(Miner* Unit) 
{
		cout << "ZZZZzzzZZZ...\n";
		static int sleepCounter;
		sleepCounter++;
		if ( sleepCounter > 2 )
		{
			sleepCounter = 0;
			Unit->ChangeState(Working().instance());
		}
}

void Working::Execute(Miner* Unit) 

{
		cout << "Working is making me tired\n";
		static int Work;
		Work++;
		if ( Work > 4 )
		{
			Work = 0;
			Unit->ChangeState(Sleeping().instance());
		}
	}



1
2
3
4
5
6
7
8
9
10
11
12
#include "Miner.h"
#include "States.h"
#include <iostream>
int main()
{
	Miner Tom;
	for ( int i = 0; i < 10; i++ )
	{
		Tom.update();
	}
	cin.get();
}
Last edited on
Do you get any errors there?

Generally, you can use:
class A; to forward declare a pointer only. If you want to use a method or access a member, you need to #include that class's header.

This is how I do it:
1
2
3
4
5
6
7
8
9
10
11
class B;
class A
{
    B* b;
public:
    void method(); // this will manipulate b, but we don't say that here;
};
class C : public A
{
    // ...
};

1
2
3
4
5
6
7
class C; // You don't need to know about class A here
class B;
{
    C* c;
pubic:
    void method();
}

1
2
3
4
5
6
7
#include "classB.h"
#include "classAC.h" // This is only place we need the full declaration of class A and C

void B::method()
{
    c->method();
}
Last edited on
closed account (ETAkoG1T)
I need to use singleton classes for states. So I can't just declare it inside the class even if that would work. If you are interested to help me further you should take a look at the code.
You're including headers in each other - don't do that.
If you are interested to help me further you should take a look at the code.

If you are interested in being helped, you should pay attention to what is being said to you. You cannot define methods in the class (A) which require the full definition of another class (B) for which the full definition (of class B) is not available. The obvious solution is to move those method definitions outside of the class definition. One usually puts them into a source (.cpp) file. In that source file, one may #include whatever headers are necessary, because those headers will not be including each other. This also has the benefit of separating the interface (in the header file) from the implementation (in the source file.)

closed account (ETAkoG1T)
Atleast now I know why my c++ book insists on using a seperate file for declaring functions from the classes :)
Topic archived. No new replies allowed.