2013-12-23 9 views
1

Я пытаюсь попасть на C++, и у меня возникло несколько проблем. Мои два класса выглядит так:Указатели и круговые зависимости

#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); 
}; 

Передавая экземпляр класса Account к SetAccount функции я делаю копию этого или я передаю его в качестве ссылки? Насколько я понимаю, я делаю копию, но я хотел быть уверенным. Чтобы передать его в качестве ссылки, мне нужно использовать указатели, не так ли?

Другая проблема, с которой я столкнулся, - это мой класс учетной записи. Допустим, что в какой-то момент необходимо иметь ссылку на класс программы. Проблема состоит в том, что как классы программы, так и учетные записи имеют строки «#include» друг для друга, поэтому она вызывает циклическую зависимость. Есть идеи, как их решить?

Отредактированные

Мои классы теперь выглядит так:

#include "Account.h" 

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

class Program; 

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

Когда я пытаюсь инициализировать * программу в конструкторе Account я получаю «неполный тип не допускается» и «„Программы“: нет подходящего конструктора по умолчанию ".

ответ

2

В вашем определении

void SetAccount(Account account); 

класс Account должен быть известен в compiletime, так что вы должны включать определение перед ним.

В вашем классе счета вы используете только указатель, так что вы можете сделать опережающее объявление

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

Это просто, чтобы сообщить компилятору, что определение объекта с именем Program существует, но размер объект не обязательно известен. Пока требуется только указатель, этого достаточно. Если вы хотите разыменовать такой указатель, вы должны указать определение класса.

+1

Как вы его инициализируете? Если вы выполняете 'program = NULL;', это будет работать. Если вы попытаетесь создать новый объект с помощью 'new Program();' тогда вы должны, конечно, знать размер, а это значит, что вы должны предоставить файл include. Операции указателей можно выполнять только с помощью прямого объявления. – Devolus

+0

Я просто спросил то же самое выше, на другой ответ. Хотелось бы получить ответ на него. – martynaspikunas

+0

Какая ошибка вы получаете и как выглядит ваш текущий код? – Devolus

2

В вашем классе Account вам не нужно полное определение Program, так как вы только объявляете указатель. Таким образом, вы можете уйти с форвардной декларацией, вместо того, чтобы включать Program.h.

class Program; 

class Account 
{ 
public: 
    Program *program; 
    // ... 
+0

Так что это помогло мне избавиться от этой ошибки, но теперь у меня есть новая. Когда я пытаюсь инициализировать * программу в конструкторе Account, я получаю «неполный тип не разрешен» и «« Программа »: никакого подходящего конструктора по умолчанию не существует». – martynaspikunas

+0

@martynaspikunas Удалить декларацию 'Program (void);'. Если вы не выполнили 'Program()', чтобы выполнить некоторую инициализацию в файле cpp, вам это не понадобится, поскольку по умолчанию компилятор будет работать нормально. Также вам не нужно 'void' в качестве аргумента. Это только C. – en4bz

1

Чтобы передать ссылку вы можете, по сути, передать ссылку:

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

Это предпочтительно передавать по значению, как вам не нужно, чтобы сделать копию и так быстрее, и const вы также гарантируете, что внутренняя часть функции не разрушит ваш объект или каким-либо образом его не изменит.

Что касается конкретной проблемы, вы можете просто использовать forward declaration и написать

class Program; 

в верхней части счета, так как ему не нужно ничего знать о внутренностях программы просто использовать указатель Это.

1

Чтобы избежать круговой включает в себя, использовать общую стратегию ограждающих код заголовка файла в директиве препроцессора:

программы.H:

#ifndef PROGRAM_H 
#define PROGRAM_H 1 

#include "Account.h" 

class Program 
{ 
    // ... 
}; 

#endif 
Смежные вопросы