将一个类的对象声明为另一个(C ++)的成员

时间:2019-02-10 00:21:26

标签: c++ class c++11 object member

由于某种原因,我的编译器不允许我将另一个类的对象用作另一个类的成员。这是我的代码:

在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未命名类型,并且未在该范围内声明该类型。我尝试过将成员公开和不公开,以及在公开和不公开中宣布朋友类别。我也尝试过使用指向对象的指针。我究竟做错了什么?谢谢。

1 个答案:

答案 0 :(得分:0)

根据您描述的错误,您尚未提供MVCE

  

错误:“参数”未命名类型

您似乎在Parameter.hPredicate.h之间遇到了“圆形包含”,如评论中所建议。

当您声明两个彼此都知道的类(ParameterPredicate)时,就会发生这种情况。考虑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