1

I am trying to get into C++ and I encountered few issues. My two classes look like that:

#include "Account.h"

class Program
{
public:
    Program(void);
    ~Program(void);
    void SetAccount(Account account);
};

#include "Program.h"

class Account
{
public:
    Program *program;
    Account(void);
    ~Account(void);
};

By passing an instance of the Account class to SetAccount function am I making a copy of it or I am passing it as a reference? As I understand I am making a copy of it, but I wanted to be sure. To pass it as a reference I need to use pointers, right?

Another issue I encountered is with my Account class. Lets say it needs to have Program class reference at some point. The problem is that both Program and Account classes have lines "#include" to each other so it causes circular dependency. Any ideas how to solve it?

Edited

My classes now looks like that:

#include "Account.h"

class Program
{
public:
    Program();
    ~Program();
    void SetAccount(Account account);
};

class Program;

class Account
{
public:
    Program *program;
    Account();
    ~Account();
};

When I try to initialize *program in Account constructor I get "incomplete type is not allowed" and "'Program' : no appropriate default constructor available".

martynaspikunas
  • 485
  • 5
  • 15

4 Answers4

2

In your Account class you don't need the full definition of Program since you're only declaring a pointer. Thus you can get away with a forward declaration instead of including Program.h.

class Program;

class Account
{
public:
    Program *program;
    // ...
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • So it helped me to get rid of that error, but now I have a new one. When I try to initialize *program in Account constructor I get "incomplete type is not allowed" and "'Program' : no appropriate default constructor available". – martynaspikunas Dec 23 '13 at 18:19
  • @martynaspikunas Remove the `Program(void);` declaration. Unless you've implemented `Program()` to do some initialization in the cpp file you don't need it as the compiler default will work fine. Also you don't need `void` as an argument. That's C only. – en4bz Dec 23 '13 at 18:30
2

In your definition of

void SetAccount(Account account);

the class Account must be known at compiletime, so you have to include the definition before it.

In your account class you are using only a pointer, so you can make a forward declaration

class Program;
class Account
{
public:
    Program *program;
   ...
};

This is just to tell the compiler that a definition of an object named Program exists, but the size of the object is not necessarily known. As long as only a pointer is required, that is enough. If you want to dereference such a pointer you have to provide the class definition then.

Devolus
  • 21,661
  • 13
  • 66
  • 113
  • 1
    How do you initiliaze it? If you do `program = NULL;` that will work. If you try to create a new object with `new Program();` then you must of course know the size, which means you must provide the include file. You can only do pointer operations with a forward declaration. – Devolus Dec 23 '13 at 18:20
  • I just asked the same thing above, on another answer. Would love to get an answer to it. – martynaspikunas Dec 23 '13 at 18:23
  • When you want to use `new Program()` in your `cpp` file you must include `Program.h` otherwise the size of `Program` will not be known. – Devolus Dec 23 '13 at 18:44
  • Ok, but then I get back to my first problem that I stated in my question. Do you know how to solve it? – martynaspikunas Dec 23 '13 at 18:51
  • YOur object model is wrong if you need the full definition in two different objects which reference each other. You must use pointers instead of references, or you must rethink how the objectrs relate to ech other. – Devolus Dec 23 '13 at 18:57
  • Well I understand that I am doing something wrong, but I would also like to see a solution to my problem. – martynaspikunas Dec 23 '13 at 19:00
  • You should create a small full sample code SSCE and post it, because with those snippets it's hard to say what you are trying to achieve. – Devolus Dec 23 '13 at 19:05
  • I just realized myself that my model of the problem is wrong. Fixed it and now everything is fine. Thank you for your help. – martynaspikunas Dec 23 '13 at 19:29
1

To pass a reference you can, in fact, pass a reference:

class Program
{
public:
    Program(void);
    ~Program(void);
    void SetAccount(const Account &account);
};

This is preferred to pass by value as you don't need to make a copy and so is faster, and by const you also ensure that the inside of the function doesn't break your object or modify it in any way.

As for your specific problem, you can just use forward declaration and write

class Program;

at the top of Account, as it doesn't need to know anything about the insides of Program to just use a pointer to it.

Community
  • 1
  • 1
user2711915
  • 2,704
  • 1
  • 18
  • 17
1

To avoid circular includes, use the common strategy of enclosing the header file code within a preprocessor directive:

Program.H:

#ifndef PROGRAM_H
#define PROGRAM_H 1

#include "Account.h"

class Program
{
    // ...
};

#endif
Zymurgeek
  • 169
  • 7