проблема циклического включения
Я жду объявления одного из классов в заголовке другого в попытке решить их циклическое включение. Вот мои два файла:
Первый файл (Parameter.h):
#pragma once
#include "Token.h"`
class Expression;
class Parameter {
public:
Parameter() {
string = new Token();
identifier = new Token();
expr = new Expression();
}
Token* string;
Token* identifier;
Expression* expr;
};
Второй файл (Expression.h):
#pragma once
#include "Token.h"#include "Parameter.h"
class Expression {
public:
Expression() {
param1 = new Parameter();
param2 = new Parameter();
op = new Token();
}
Expression(Parameter* p1, Token* o, Parameter* p2) {
param1 = p1;
param2 = p2;
op = o;
}
Parameter* param1;
Parameter* param2;
Token* op;
};
Как видите, я пересылаю объявление Expression в Parameter.h, но я по-прежнему получаю следующие две ошибки:
предварительное объявление ‘struct Expression’
недопустимое использование неполного типа ‘выражение структуры’
Я просмотрел несколько ранее опубликованных вопросов, но все же не смог решить эту проблему. Благодарю.
Вы не можете переслать объявить Expression
потому что вам нужна полная декларация для этого:
Parameter() {
string = new Token();
identifier = new Token();
expr = new Expression(); // here!
}
Что вы можете сделать, это переместить реализацию Parameter()
Конструктор из заголовка и в .cpp
файл.
Вам нужно поместить конструктор параметров в файл cpp, когда вы вызываете expr = new Expression();
в конструкторе должен быть известен конкретный тип Expression.
Parameter.h
#pragma once
#include "Token.h"
class Expression;
class Parameter {
public:
Parameter();
Token* token;
Token* identifier;
Expression* expr;
};
Parameter.cpp
#include "Parameter.h"
Parameter::Parameter()
: token(new Token()),
identifier(new Token()),
expr(new Expression())
{
}
примечание стороны: могли бы использовать умные указатели вместо сырых указателей в качестве члена класса? также имя переменной string
может повлиять с std::string
,
Определите тело конструктора в отдельном файле cpp. Предварительное объявление класса позволяет вам использовать указатели или ссылки, не являющиеся конструктором объявленного заранее класса, как вы используете в конструкторе «другого» класса.
в файле ccp:
#include "Parameter.h"#include "Expression.h" // ??
Parameter::Parameter(): string (new Token()),
identifier(new Token()),
expr ( new Expression())
{}Expression::Expression() param1 (new Parameter()),
param2 (new Parameter()),
op ( new Token())
{ }
(теперь вы в безопасности, если новые / конструкторы бросают)