2

Possible Duplicate:
Avoiding Circular Dependencies of header files

Task.h:

#ifndef Tasks_h
#define Tasks_h

#include "Executors.h"

class Task
{
    Executor *current_executor;
};

#endif Tasks_h

Executor.h:

#ifndef Executors_h
#define Executors_h

#include "Tasks.h"

class Executor
{
    Task *current_task;
};

#endif Executors_h

main.cpp:

#include <conio.h>
#include <stdio.h>
#include "Tasks.h"
#include "Executors.h"

int main()
{
    Executor ex;

    return 0;
}

Compilation errors:

Error   1   error C2146: syntax error : missing ';' before identifier 'current_task'    c:\users\rain\documents\visual studio 2010\projects\text\text\executors.h   8
Error   2   error C4430: missing type specifier - int assumed. Note: C++ does not support default-int   c:\users\rain\documents\visual studio 2010\projects\text\text\executors.h   8
Error   3   error C4430: missing type specifier - int assumed. Note: C++ does not support default-int   c:\users\rain\documents\visual studio 2010\projects\text\text\executors.h   8

Again... in C# i never can meet such problems, but i do my best to support C++ and use it.
Don't want to code all classes in one header file

Community
  • 1
  • 1
Kosmo零
  • 4,001
  • 9
  • 45
  • 88
  • 3
    The code doesn't make sense. `Executor` object contains `Task` object which inturn contains `Executor` object. So its infinite recursion of objects. – Naveen Jul 16 '12 at 10:16
  • As it stands you have two classes which include instances of each other, which is clearly impossible. You need to use references or pointers to do this kind of thing. – Paul R Jul 16 '12 at 10:17
  • i know, this is just an example. there maybe be pointers instead. EDITED main question to use pointers – Kosmo零 Jul 16 '12 at 10:18

3 Answers3

4

this is just an example. there maybe be pointers instead

If you can switch to using pointers, you could replace header inclusions with forward declarations:

#ifndef Executors_h
#define Executors_h

class Task;

class Executor
{
    Task *current_task_ptr;
};

#endif Executors_h
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • can you also say how to use forward declaration for derived classes? for example if Task derives from BaseTask in it's header, how to forward declare it? like that: class Task : BaseTask;? or i can leave it like before? – Kosmo零 Jul 16 '12 at 10:26
  • @Kosmos Unfortunately, inheriting a class requires the knowledge of the structure of the class being inherited (just like including an instance of a class inside another class), and therefore cannot be solved by forward-declaring the base class. You need to keep the `#include "BaseTask.h"` – Sergey Kalinichenko Jul 16 '12 at 10:31
  • i see it also don't work if i want to call static function forward-declared class like that: class TEST_CLASS; and then somewhere in code: TEST_CLASS::RunStaticMethod(); to bad it says "use of undefined type TEST_CLASS" – Kosmo零 Jul 16 '12 at 10:50
  • @Kosmos Forward declaration gives you an ability to create a pointer to a class, but almost nothing else (no inheritance, no function calls, etc.) The reason for it is that pointers to classes are all created equal. Knowing that the class is defined somewhere is all the C++ compiler needs in order to allocate space for a pointer. Inheriting, including in a class as a member, calling member functions, and so on require additional information, which is supplied in the header with the class definition. – Sergey Kalinichenko Jul 16 '12 at 12:07
3

you can use forward declaration:

//#include "Executors.h"

class Executor;
class Task
{
    std::shared_ptr<Executor> current_executor;
};

Another way is to use pimpl idiom:

in .h file (no executor headers/forward decl.)

class TaskImpl;
class Task
{
 public:
    Task();
    String getExecutorName();

 private:
    std::unique_ptr<TaskImpl> impl;
    friend TaskImpl;    
};

and in .cpp

#include "Executors.h"

class TaskImpl {
   public:
   Executor current_executor;
   String getExecutorName() { return current_executor.name; }
};

Task::Task() : impl(new TaskImpl()) {
}

String Task::getExecutorName() { return impl->getExecutorName(); }
marcinj
  • 48,511
  • 9
  • 79
  • 100
0

I bet you are not aware of what you are actually doing: you are having a Task with part of it being an Executor in which part of it being a Task in which....

It is NOT a reference as in C# or Java.

To do what you actually trying to do, make use of pointer / reference in combination of forward declaration

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131