由于某种原因,我的编译器不允许我将另一个类的对象用作另一个类的成员。这是我的代码:
在Parameter.h中:
class Parameter {
private:
string type;
string name;
public:
Parameter() {};
string toString();
friend class Predicate;
};
然后,在Predicate.h中:
#include "Parameter.h"
class Predicate {
private:
Parameter lParam;
Parameter rParam;
string type;
public:
Predicate() {};
string toString();
friend class Parameter;
};
当我尝试编译时,出现错误,提示Predicate.h中的Parameter未命名类型,并且未在该范围内声明该类型。我尝试过将成员公开和不公开,以及在公开和不公开中宣布朋友类别。我也尝试过使用指向对象的指针。我究竟做错了什么?谢谢。
答案 0 :(得分:0)
根据您描述的错误,您尚未提供MVCE,
错误:“参数”未命名类型
您似乎在Parameter.h
和Predicate.h
之间遇到了“圆形包含”,如评论中所建议。
当您声明两个彼此都知道的类(Parameter
和Predicate
)时,就会发生这种情况。考虑Predicate
。在Predicate
进行声明时,编译器需要已经知道Parameter
的存在,因为它是Predicate
中的成员。 / p>
解决方案的第一个尝试是包含Parameter.h
,它提供Parameter
的声明。但是,Parameter
要求已经声明Predicate
使其成为friend class
。这是一个循环依赖项。
解决此问题的推荐方法是使用称为 forward declaration 的东西。
// 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
的方法来解决此问题。
有关更一般性的讨论,请参见此similar question。