Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mutual class instances in C++

What is the issue with this code? Here we have two files: classA.h and classB.h

classA.h:

#ifndef _class_a_h_
#define _class_a_h_

#include "classB.h"

class B; //????

class A
{
public:
    A() {
        ptr_b = new B(); //????
    }
    
    virtual ~A() {
        if(ptr_b) delete ptr_b; //????
                    num_a = 0;
    }
    
    int num_a;
    B* ptr_b; //????
};

#endif //_class_a_h_

classB.h:

#ifndef _class_b_h_
#define _class_b_h_

#include "classA.h"

class A; //????

class B
{
public:     
    B() { 
        ptr_a = new A(); //????
                    num_b = 0;
    }
    
    virtual ~B() { 
        if(ptr_a) delete ptr_a; //????
    }
            
    int num_b;
    A* ptr_a; //????
};

#endif //_class_b_h_

when I try to compile it, the compiler (g++) says:

classB.h: In constructor ‘B::B()’:

classB.h:12: error: invalid use of incomplete type ‘struct A’

classB.h:6: error: forward declaration of ‘struct A’

classB.h: In destructor ‘virtual B::~B()’:

classB.h:16: warning: possible problem detected in invocation of delete operator:

classB.h:16: warning: invalid use of incomplete type ‘struct A’

classB.h:6: warning: forward declaration of ‘struct A’

classB.h:16: note: neither the destructor nor the class-specific operator delete will be

called, even if they are declared when the class is defined.

like image 485
sepisoad Avatar asked Dec 17 '22 01:12

sepisoad


1 Answers

You cannot create instances of an incomplete type (the compiler doesn't know anything about the class!)

You need to move the definitions of your functions (the constructor of A and B) into a C++ file that can include both headers (or into several C++ files, if you follow the convention that you have one class per file).

That having been said, your code as written has a serious problem: every A creates an instance of B and every B creates and instance of A. You will end up with an infinite recursion and you will eventually run out of memory.

Two minor nitpicks: you do not need to test whether a pointer is null before calling delete on it (it is safe to delete a null pointer), and you need to change your include guards (names beginning with an underscore in the global namespace are reserved to the implementation).

like image 161
James McNellis Avatar answered Dec 30 '22 13:12

James McNellis