Declaring an initializer class list with classes that are circular dependent



I've really tried to make this work without using pointers. I want to create a shared class where two classes "see" each other and share this object. I wanted to initialize the shared object using an initializer list, but I'm getting these errors:

1
2
3
4
error: field ‘shared_type’ has incomplete type ‘shared’
note: forward declaration of ‘class shared’
note: forward declaration of ‘class class_A’
note: forward declaration of ‘class class_B’


The first error doesn't make sense because the constructor for shared exists in shared.cpp.

I have tried declaring shared_type in class_A and class_B as const shared& shared_type;, but that gave me an error saying that the lvalue is a const and the rvalue cannot be set to const, namely the value for the initializer.

Is there anything else I could try without using pointers?

Below is the complete code.

main.cpp

1
2
3
4
5
6
7
8
9
#include <iostream>
#include "include/class_A.h"
#include "include/class_B.h"

int main()
{

    return 0;
}


class_A.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

#ifndef CLASS_A_H
#define CLASS_A_H
//#include "shared.h"
class shared;
class class_A
{
    public:

        shared shared_type;

        class_A();
        ~class_A();

    protected:

    private:
};
#endif // CLASS_A_H 


class_A.cpp

1
2
3
4
5
6
7
8
9
10
11
12

#include "class_A.h"

class_A::class_A() : shared_type()//this is the initializer for class_A
{
    //ctor
}

class_A::~class_A()
{
    //dtor
}


class_B.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#ifndef CLASS_B_H
#define CLASS_B_H
//#include "shared.h"

class shared;
class class_B
{
    public:

        const shared& shared_type;
        class_B();
        ~class_B();

    protected:

    private:
};

#endif // CLASS_B_H 


class_B.cpp
1
2
3
4
5
6
7
8
9
10
11
#include "class_B.h"

class_B::class_B() : shared_type()//this is the initializer for class_B
{
    //ctor
}

class_B::~class_B()
{
    //dtor
}


shared.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef SHARED_H_
#define SHARED_H_

//#include "class_A.h"
//#include "class_B.h"

class class_A;
class class_B;

class shared
{
    private:

        class_A type_A;
        class_B type_B;

    public:

        shared();
        ~shared();
};
#endif 


shared.cpp

1
2
3
4
#include "shared.h"

shared::shared(){}
shared::~shared(){}
First issue, class 'shared' contains a 'class_A'. class_A contains a shared. You have an "infinite recursion" of resources, which would blow up the size of your class to infinity.

Second issue,
1
2
3
4
5
6
class shared;
class class_A
{
    public:

        shared shared_type;

'shared shared_type' is an object within class_A that is being defined by value (i.e. not a reference or pointer), so the compiler needs to know the contents of shared to know how big to make class_A itself. Therefore, a forward declaration of class_A is not sufficient.

For the 'shared' object, you need to decide who 'owns' the object.
Is it
(1) class_A
(2) class_B
or (3) created outside of class_A or class_B.

You don't need to use pointers for this to work, but you would need to at least use references correctly (which are kinda like pointers that can't be null).
Last edited on
Here is one solution, which has a class that then depends on a resource by reference (which is a shared resource).

class_A and class_B are actually the same exact class logically, but I made them separate classes for purposes of example since I assume you want something about them to be different in your 'real' code.

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include "shared.h"
#include "class_A.h"
#include "class_B.h"

int main()
{
    shared shared_data(42);
    
    class_A class_a(shared_data);
    class_B class_b(shared_data);
    
    std::cout << class_a.get_shared_value() << '\n';
    
    class_a.set_shared_value(43);
    
    std::cout << class_b.get_shared_value() << '\n';
}


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

class shared;

class class_A {
public:
    class_A(shared& shared_data);
         
    int get_shared_value();
    void set_shared_value(int value);

private:
    shared& shared_data;
};

#endif 


class_A.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "class_A.h"

#include "shared.h"

class_A::class_A(shared& shared_data)
 : shared_data(shared_data) { }

int class_A::get_shared_value()
{
    return shared_data.value;
}

void class_A::set_shared_value(int value)
{
    shared_data.value = value;
}


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

class shared;

class class_B {
public:
    class_B(shared& shared_data);
         
    int get_shared_value();
    void set_shared_value(int value);

private:
    shared& shared_data;
};

#endif 


class_B.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "class_B.h"

#include "shared.h"

class_B::class_B(shared& shared_data)
 : shared_data(shared_data) { }

int class_B::get_shared_value()
{
    return shared_data.value;
}

void class_B::set_shared_value(int value)
{
    shared_data.value = value;
}


shared.h
1
2
3
4
5
6
7
8
9
10
11
#ifndef SHARED_H
#define SHARED_H

class shared {
public:
    shared(int value);
     
    int value;
};

#endif 


shared.cpp
1
2
3
4
#include "shared.h"

shared::shared(int value)
     : value(value) { }


command-line and final output
g++ -Wall main.cpp shared.cpp class_A.cpp class_B.cpp -o prog

cplusplus_285998>prog
42
43


Last edited on
Thanks, it's interesting how you didn't use a default constructor, that's the only thing that makes this work is that the constructors in both A and B have a parameter by reference.
Registered users can post here. Sign in or register to post.