将一个 class 的对象声明为另一个的成员 (C++)
Declaring objects of one class as members of another (C++)
出于某种原因,我的编译器不允许我将另一个 class 的对象用作另一个 class 的成员。这是我的代码:
在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 中的参数未命名类型,并且未在该范围内声明。我试过将成员放在私人和 public 中,并在私人和 public 中声明朋友 class。我也尝试过使用指向对象的指针。我究竟做错了什么?谢谢
虽然您尚未提供 MVCE,但基于您描述的错误:
error: ‘Parameter’ does not name a type
您似乎正在经历 Parameter.h
和 Predicate.h
之间的 'circular include',正如评论中所建议的那样。
当您声明 两个 class 都知道对方(Parameter
和 Predicate
)时,就会发生这种情况。考虑 Predicate
。在 Predicate
的 声明 时,编译器需要已经知道 Parameter
的存在,因为它作为成员出现在 Predicate
.
解决方案的第一个尝试是包含 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
而不会出现问题,因为循环依赖已被打破。
请注意,如果您从 header 中的 Parameter
调用任何 Predicate
的方法,前向声明将不起作用。这是因为需要完整的 class 声明才能调用任何方法。您可以通过在源文件中实现 Parameter
的方法来解决这个问题。
请参阅此 similar question 以获得更一般的讨论。
出于某种原因,我的编译器不允许我将另一个 class 的对象用作另一个 class 的成员。这是我的代码:
在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 中的参数未命名类型,并且未在该范围内声明。我试过将成员放在私人和 public 中,并在私人和 public 中声明朋友 class。我也尝试过使用指向对象的指针。我究竟做错了什么?谢谢
虽然您尚未提供 MVCE,但基于您描述的错误:
error: ‘Parameter’ does not name a type
您似乎正在经历 Parameter.h
和 Predicate.h
之间的 'circular include',正如评论中所建议的那样。
当您声明 两个 class 都知道对方(Parameter
和 Predicate
)时,就会发生这种情况。考虑 Predicate
。在 Predicate
的 声明 时,编译器需要已经知道 Parameter
的存在,因为它作为成员出现在 Predicate
.
解决方案的第一个尝试是包含 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
而不会出现问题,因为循环依赖已被打破。
请注意,如果您从 header 中的 Parameter
调用任何 Predicate
的方法,前向声明将不起作用。这是因为需要完整的 class 声明才能调用任何方法。您可以通过在源文件中实现 Parameter
的方法来解决这个问题。
请参阅此 similar question 以获得更一般的讨论。