Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++:由于包含循环,无法将对象实例传递给另一个类_C++_Class_Include - Fatal编程技术网

C++:由于包含循环,无法将对象实例传递给另一个类

C++:由于包含循环,无法将对象实例传递给另一个类,c++,class,include,C++,Class,Include,假设我有两门课: // a.h #ifndef A_H #define A_H #include "b.h" class A { public: void a() { B* b = new B(this); } } #endif // b.h #ifndef B_H #define B_H #include "a.h" class B { public: B(A* a) { // ... } } #endif 此代码将引发错误A“尚未声明”,因

假设我有两门课:

// a.h
#ifndef A_H
#define A_H

#include "b.h"

class A {
  public: void a() {
    B* b = new B(this);
  }
}

#endif


// b.h
#ifndef B_H
#define B_H

#include "a.h"

class B {
  public: B(A* a) {
     // ...
  }
}

#endif
此代码将引发错误A“尚未声明”,因为类A引用了类B,而类B又引用了尚未在A.h中声明的类A


那么,如何将A的实例传递给B呢?

您可以在单独的文件中移动实现。这样,您就不必将B.h包含在A.h中:


您可以在单独的文件中移动实现。这样,您就不必将B.h包含在A.h中:

你需要

将B构造函数的pass-by-value参数更改为pointer或reference* 将B::B的定义移动到cpp文件这将删除对A定义的任何直接依赖,并允许您 B.h.中的转发声明A:

注意,我为a&constructor参数添加了一个常量限定符,因为我假设您不想在B的构造函数中修改a

当然,您也可以通过将A::A的定义和相应的include b.h移动到A.cpp中来实现这一点

*无论如何,您都应该这样做,因为您不太可能希望通过值传递对象。通过值传递对象意味着隐式创建对象的副本并将其推送到堆栈上。哪个

意味着对参数对象所做的更改不会影响原始对象,这通常不是您想要的,因此是错误的来源, 包括创建和销毁临时, 通常比引用/指针消耗更多内存, 为虫子开门。 你需要

将B构造函数的pass-by-value参数更改为pointer或reference* 将B::B的定义移动到cpp文件这将删除对A定义的任何直接依赖,并允许您 B.h.中的转发声明A:

注意,我为a&constructor参数添加了一个常量限定符,因为我假设您不想在B的构造函数中修改a

当然,您也可以通过将A::A的定义和相应的include b.h移动到A.cpp中来实现这一点

*无论如何,您都应该这样做,因为您不太可能希望通过值传递对象。通过值传递对象意味着隐式创建对象的副本并将其推送到堆栈上。哪个

意味着对参数对象所做的更改不会影响原始对象,这通常不是您想要的,因此是错误的来源, 包括创建和销毁临时, 通常比引用/指针消耗更多内存, 为虫子开门。
您可以使用以下语法向前声明一个类

class A;
在b.h文件中,这足以告诉编译器有一个名为a的类,您将引用该类。它不允许您访问该类的内部,例如您没有告诉它有哪些成员,或者它有多大,但它足以用作指针或引用


您可以做的另一件事是查看您的设计,并尝试删除此类循环依赖项。

您可以使用语法向前声明一个类

class A;
在b.h文件中,这足以告诉编译器有一个名为a的类,您将引用该类。它不允许您访问该类的内部,例如您没有告诉它有哪些成员,或者它有多大,但它足以用作指针或引用


您可以做的另一件事是查看您的设计,并尝试删除此类循环依赖项。

在定义的代码中存在更严重的错误,新的B…如此多的重复:可能重复@KonradRudolph,为什么包含保护使用定义错误?另一种选择是pragma一次,但尽管它得到广泛支持并具有优势,但这不是标准吗?最好的做法是什么?@Pé在编辑代码后,原始版本使用A和B作为包含保护的名称…代码中有更严重的错误,新的B…如此多的重复:可能是@KonradRudolph的重复,为什么包含保护使用定义错误?另一种选择是pragma一次,但尽管它得到广泛支持并具有优势,但这不是标准吗?最好的做法是什么?@Péter代码经过编辑,原始版本使用A和B作为包含守卫的名称……这很有效,谢谢。但当我在B中调用A类的某个方法时,我得到了不完整类型A的无效使用和结构A的转发声明。是的,我当然想传递引用,我已经更新了我的帖子。@Alex,请给我们看相应的代码,标记它是在.h还是.cpp文件中。@Alex,更新代码中的A*是指针,不是指a。后者应该是a&@PéterTörök:我大体上同意你的说明,但问题是你说的是“需要”,而实际上并不需要。我以为你这么说是因为
很多人认为,如果你所拥有的只是一个远期声明,那么你就不能通过价值传递,这是错误的。此外,有时您应该传递值。有时您仍然需要复制对象,最好的方法是在参数列表中允许移动语义,或者在您碰巧获得右值的情况下可能会进行复制省略。这很有效,谢谢。但当我在B中调用A类的某个方法时,我得到了不完整类型A的无效使用和结构A的转发声明。是的,我当然想传递引用,我已经更新了我的帖子。@Alex,请给我们看相应的代码,标记它是在.h还是.cpp文件中。@Alex,更新代码中的A*是指针,不是指a。后者应该是a&@PéterTörök:我大体上同意你的说明,但问题是你说的是“需要”,而实际上并不需要。我认为你这么说是因为很多人认为如果你只有一个远期声明,你就不能通过价值传递,这是错误的。此外,有时您应该传递值。有时您仍然需要复制对象,最好的方法是在参数列表中允许移动语义,或者在您碰巧获得右值的情况下,复制省略。
class A;