8

Say there are two classes, which need each other: container and item. The class container creates instances of class item. Each instance of class item holds an instance of class container and needs to call only the method method_called_by_item of class container. Class container needs to see all fields of class item.

The problem is the forward declaration: I want to have a forward declaration inside of item.h, so that the class item can have a container as field and call the method method_called_by_item. How do I do that?

Class container, which creates items.

// container.h
#ifndef CONTAINER_H
#define CONTAINER_H

#include "item.h"

class container{

public:
  item * create_item();
  void method_called_by_item(item * i);
};

#endif //CONTAINER_H

The implementation:

// container.cpp
#include "container.h"

item * container::create_item(){
  return new item(this);
}

void container::method_called_by_item(item * i){
  // do stuff with item
}

The class item, which needs to call one method of container:

// item.h
#ifndef ITEM_H
#define ITEM_H

#include <iostream>

class container;

class item{

public:
  item(container * c);
  void do_something();
  container * c;
};

#endif //ITEM_H

The implementation:

// item.cpp
#include "item.h"

item::item(container * c){
  this->c = c;
}
void item::do_something(){
  this->c->method_called_by_item(this);
}
Dev
  • 2,326
  • 24
  • 45
clx
  • 794
  • 2
  • 8
  • 19

2 Answers2

11

in container.h

class item; // do not include the item.h

in container.cpp

#include "item.h"

in item.h

class container; // do not include container.h

in item.cpp

#include "container.h"
Mahmoud Fayez
  • 3,398
  • 2
  • 19
  • 36
5

You have already added the forward declaration to item.h so all you need to do is add the following line to item.cpp.

#include "container.h"

container.h already includes item.h so you don't have to make any additional changes but as Mahmoud Fayez pointed out you can add a forward declaration there as well. This will remove the dependency on the header file which is typically desired - it can reduce build times on large projects and allows the header file to "stand on it's own".

Community
  • 1
  • 1
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
  • Now, how do you get the destructors called when using shared_ptr now that these classes are referencing each other? – James Nov 05 '16 at 23:15
  • @James you'll need to either manually break the circular reference or use `std::weak_ptr` as appropriate. – Captain Obvlious Nov 06 '16 at 01:09
  • Obvious I tried weak_prt and discovered there was no -> operator so I was unable to access any member functions. But I figured out what was happening. I did some more research and discovered that I should in fact be using standard pointers to pass into functions and maintain references to parent/child classes. Once I did that, the destructors started getting called. – James Nov 06 '16 at 21:56
  • @James There is no `->` operator for _good_ reason - you don't know if the weak pointer references a valid object or not. You need to call `lock` to get a shared pointer to the object references by `weak_ptr`. Using raw pointers here is a terrible idea and defeats the purpose of expressing and managing lifetime and ownership with smart pointers. – Captain Obvlious Nov 07 '16 at 21:37