Circular dependency linker errors

I am stuck on the second example. I appreciate any help you can give me.

In the first example, two classes call each other. It works as intended.

Example 1:
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
#include <iostream>

class BClass;

class AClass
{
    private:
        BClass* ptrBClass;
    public:
        void init(BClass* ptr);
        void printB();
        void print();    
};

class BClass
{
    private:
        AClass& refAClass;
    public:
        BClass(AClass& refAClass);
        void printA();
        void print();
};

//define the functions after both class declarations
void AClass::init(BClass* ptr) { ptrBClass = ptr; }
void AClass::printB() { ptrBClass->print(); }
void AClass::print() { std::cout << 'a' << std::endl; }

BClass::BClass(AClass& refAClass) : refAClass(refAClass) { }
void BClass::printA() { refAClass.print(); }
void BClass::print() { std::cout << 'b' << std::endl; }

AClass aObject;
BClass bObject(aObject);

int main()
{
    //the first object in a circlular depencency must initialize a pointer
    //because a refernce could not be changed to refer to a different object
    aObject.init(&bObject);
    aObject.printB();

    bObject.printA();
}


output is as expected:
1
2
b
a


The second example uses the same code as the first example, but the class declarations and implementations moved to separate files.
It gets these linker errors:
1
2
3
4
5
6
7
/tmp/ccLYmASa.o: In function `main':
circular_dependency.cpp:(.text+0xf): undefined reference to `AClass::init(BClass*)'
circular_dependency.cpp:(.text+0x19): undefined reference to `AClass::printB()'
circular_dependency.cpp:(.text+0x23): undefined reference to `BClass::printA()'
/tmp/ccLYmASa.o: In function `__static_initialization_and_destruction_0(int, int)':
circular_dependency.cpp:(.text+0x74): undefined reference to `BClass::BClass(AClass&)'
collect2: error: ld returned 1 exit status

How to fix the linker errors?

Thank you.

Example 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "AClass.h"
#include "BClass.h"

AClass aObject;
BClass bObject(aObject);

int main()
{
    //the first object in a circlular depencency must initialize a pointer
    //because a refernce could not be changed to refer to a different object
    aObject.init(&bObject);
    aObject.printB();

    bObject.printA();
}


AClass.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef ACLASS_H
#define ACLASS_H

#include <iostream>

class BClass;

class AClass
{
    private:
        BClass* ptrBClass;
    public:
        void init(BClass* ptr);
        void printB();
        void print();    
};
#endif 


AClass.cpp:
1
2
3
4
5
6
7
//define the functions after #including both header files
#include "AClass.h"
#include "BClass.h"

void AClass::init(BClass* ptr) { ptrBClass = ptr; }
void AClass::printB() { ptrBClass->print(); }
void AClass::print() { std::cout << 'a' << std::endl; }


BClass.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef BCLASS_H
#define BCLASS_H

#include <iostream>

class AClass;

class BClass
{
    private:
        AClass& refAClass;
    public:
        BClass(AClass& refAClass);
        void printA();
        void print();
};
#endif 


BClass.cpp:
1
2
3
4
5
6
7
//define the functions after #including both header files
#include "AClass.h"
#include "BClass.h"

BClass::BClass(AClass& refAClass) : refAClass(refAClass) { }
void BClass::printA() { refAClass.print(); }
void BClass::print() { std::cout << 'b' << std::endl; }
Last edited on
What are you trying to do? It appears you are declaring class BClass; and class AClass; in the opposite class files?

Why are you doing this? It seems a little odd.
Last edited on
Hi Bdanielz,

I was trying to make an example of a circular dependency that is simple and clear.
The solution will be applied to a real-world problem.
Each class contains a reference to the other class, which makes it a circular dependency.

In the real-world problem, the two classes are a State class and a Display class.
When the State class changes, it calls the Display class, passing relevant state information to the Display class, which then displays the state.
This is a one-way flow of information (not circular).
However, there is an exception that makes the State-Display relation circular.
One of the displays is animated and takes 2 seconds to complete.
The Display class does not store state information.
At the end of the 2 seconds, the Display class calls the State class to get the current state and then continues to display the current state.
Last edited on
The following code has the .cpp files #included in main, and it works.
This arrangement of #includes seems a bit strange to me. Is this how it is normally done?

Example 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "AClass.h"
#include "BClass.h"
#include "AClass.cpp"
#include "BClass.cpp"

AClass aObject;
BClass bObject(aObject);

int main()
{
    //the first object in a circlular depencency must initialize a pointer
    //because a refernce could not be changed to refer to a different object
    aObject.init(&bObject);
    aObject.printB();

    bObject.printA();
}


AClass.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef ACLASS_H
#define ACLASS_H

#include <iostream>

class BClass;

class AClass
{
    private:
        BClass* ptrBClass;
    public:
        void init(BClass* ptr);
        void printB();
        void print();    
};
#endif 


AClass.cpp:
1
2
3
4
5
//#include moved to main

void AClass::init(BClass* ptr) { ptrBClass = ptr; }
void AClass::printB() { ptrBClass->print(); }
void AClass::print() { std::cout << 'a' << std::endl; }


BClass.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef BCLASS_H
#define BCLASS_H

#include <iostream>

class AClass;

class BClass
{
    private:
        AClass& refAClass;
    public:
        BClass(AClass& refAClass);
        void printA();
        void print();
};
#endif 


BClass.cpp:
1
2
3
4
5
//#include moved to main

BClass::BClass(AClass& refAClass) : refAClass(refAClass) { }
void BClass::printA() { refAClass.print(); }
void BClass::print() { std::cout << 'b' << std::endl; }


output is as expected:
1
2
b
a
Last edited on
Topic archived. No new replies allowed.