将一个 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.hPredicate.h 之间的 'circular include',正如评论中所建议的那样。

当您声明 两个 class 都知道对方(ParameterPredicate)时,就会发生这种情况。考虑 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 以获得更一般的讨论。