Хотя вы еще не предоставили MVCE , основываясь на описанной вами ошибке:
error: «Параметр» не называет тип
вы, похоже, испытываете "круговое включение" между Parameter.h
и Predicate.h
, как предлагается в комментариях.
Это происходит, когда вы объявляете два класса, которые обазнать о другом (Parameter
и Predicate
).Рассмотрим Predicate
.Во время Predicate
объявления компилятору уже нужно знать о существовании Parameter
, так как он появляется как член в Predicate
.
Первыйпопытка решения будет включать Parameter.h
, что обеспечивает объявление Parameter
.Но, Parameter
требует, чтобы Predicate
уже было объявлено, чтобы сделать его friend class
.Это круговая зависимость .
Рекомендуемый метод решения этой проблемы - использовать так называемое предварительное объявление .
// Parameter.h
#pragma once
#include <string>
class Predicate; // Forward declare Predicate
class Parameter {
private:
std::string type;
std::string name;
public:
Parameter() {};
std::string toString() { return "Parameter"; };
friend class Predicate;
};
Таким образом, это позволяет нам завершить объявление Parameter
без необходимости включать весь файл Predicate.h
.С другой стороны, Predicate.h
может продолжать включать Parameter.h
без проблем, поскольку циклическая зависимость была нарушена.
Обратите внимание, что если вы вызываете любой из Predicate
методов из Parameter
взаголовок, предварительные объявления не будут работать.Это потому, что для вызова любых методов необходимо полное объявление класса.Вы можете обойти это путем реализации методов Parameter
в исходном файле.
См. Этот аналогичный вопрос для более общего обсуждения.