C++ #include 循环
C++ #include Loop
文件Dog.h
#ifndef DOG_H
#define DOG_H
#include "Cat.h"
//class Cat;
class Dog
{
Cat c;
};
#endif
文件Cat.h
#ifndef CAT_H
#define CAT_H
#include "Dog.h"
//class Dog;
class Cat
{
Dog d;
};
#endif
这会导致循环,问题是 类 都需要了解对方;前向声明也不能解决问题。您可以创建 Dog d 或 Cat c 的指针来解决它。
问题:是否真的没有办法不创建指针,即保持代码原样而不重写我想要的代码?
你想做的事是不可能的。您的 class 需要无限 space.
你得到了一个 Dog
,它有一个 Cat
成员变量,它有一个 Dog
成员变量,它有一个 Cat
成员变量,它有一个 Dog
成员变量...
如果不在某处用指针破坏它,你最终会得到无限递归成员变量占用无限内存,这是不可能的。
请注意,由于无限递归,编译器甚至无法实际计算 Dog
或 Cat
所需的内存。但是由于 C++ 中的 class 通常不能 0
大小,我们知道它无论如何都会是无限的 space。
其他答案也给出了很好的观点,即 'Chicken and Egg' 必须先定义一个才能定义另一个的问题。
我只想补充一点,相互递归 classes 是一种奇怪的东西,如果你能以其他方式设计它,最好避免。如果您真的必须使用它们,请确保您确实打破了递归性。否则,如果你有一个天真的实现,它的指针会无限相互递归 new
调用,那么你只能将它从编译时由于无限相互递归导致的错误转移到 运行 内存不足和运行时崩溃施工时间。
不,这不可能,与包含文件无关。
原因是如果你创建一个 class 其中包含另一个 class 作为成员(而不是指针),编译器需要为那个 space 添加一些 class进入另一个class。例如,如果您创建这样的内容:
class Dog {
std::string name;
std::string owner;
};
class Person {
Dog pet;
std::string name;
};
然后上例中 class Person
的实例的大小为 sizeof(std::string) + sizeof(Dog)
,而 class Dog
的实例的大小为 sizeof(std::string) + sizeof(Dog)
尺寸为 sizeof(std::string) * 2
;所以 Person 的大小是 sizeof(std::string) * 3
(模对齐差异)
换句话说,C++ 中第一个 class 变量(相对于指针)所需的内存被分配 作为 实例的一部分,并且不是指针;这与 struct
s 的工作方式非常相似。事实上,在 C++ 中 class
和 struct
关键字之间确实没有实际区别,除了 class 默认是 private
而结构是public
.
除了这会导致一个无限的 space 对象(正如 Raphael 所解释的),编译器不会让这种情况发生,如 question 中所解释的那样。当你在 Dog
class 中使用它时,他不知道 Cat
class,所以它不会因为同样的原因而不起作用:
class B;
class A{
B b;
};
正如已经指出的那样,您不能直接或间接地定义一个没有间接寻址的成员的对象。
如果您只想使用 .
语法而不是 ->
语法,您可以使用引用而不是指针。例如:
// in Dog.h
class Cat;
class Dog {
public:
std::unique_ptr<Cat> catp;
Cat &c;
Dog ();
Dog (Cat &);
};
// in Cat.h
class Cat {
public:
std::unique_ptr<Dog> dogp;
Dog &d;
Cat ();
Cat (Dog &);
}
现在,在您的源代码中,您可以这样做:
#include "Dog.h"
#include "Cat.h"
Dog::Dog () : catp(new Cat(*this)), c(*catp) {}
Cat::Cat () : dogp(new Dog(*this)), d(*dogp) {}
Dog::Dog (Cat &cat) : c(cat) {}
Cat::Cat (Dog &dog) : d(dog) {}
文件Dog.h
#ifndef DOG_H
#define DOG_H
#include "Cat.h"
//class Cat;
class Dog
{
Cat c;
};
#endif
文件Cat.h
#ifndef CAT_H
#define CAT_H
#include "Dog.h"
//class Dog;
class Cat
{
Dog d;
};
#endif
这会导致循环,问题是 类 都需要了解对方;前向声明也不能解决问题。您可以创建 Dog d 或 Cat c 的指针来解决它。
问题:是否真的没有办法不创建指针,即保持代码原样而不重写我想要的代码?
你想做的事是不可能的。您的 class 需要无限 space.
你得到了一个 Dog
,它有一个 Cat
成员变量,它有一个 Dog
成员变量,它有一个 Cat
成员变量,它有一个 Dog
成员变量...
如果不在某处用指针破坏它,你最终会得到无限递归成员变量占用无限内存,这是不可能的。
请注意,由于无限递归,编译器甚至无法实际计算 Dog
或 Cat
所需的内存。但是由于 C++ 中的 class 通常不能 0
大小,我们知道它无论如何都会是无限的 space。
其他答案也给出了很好的观点,即 'Chicken and Egg' 必须先定义一个才能定义另一个的问题。
我只想补充一点,相互递归 classes 是一种奇怪的东西,如果你能以其他方式设计它,最好避免。如果您真的必须使用它们,请确保您确实打破了递归性。否则,如果你有一个天真的实现,它的指针会无限相互递归 new
调用,那么你只能将它从编译时由于无限相互递归导致的错误转移到 运行 内存不足和运行时崩溃施工时间。
不,这不可能,与包含文件无关。
原因是如果你创建一个 class 其中包含另一个 class 作为成员(而不是指针),编译器需要为那个 space 添加一些 class进入另一个class。例如,如果您创建这样的内容:
class Dog {
std::string name;
std::string owner;
};
class Person {
Dog pet;
std::string name;
};
然后上例中 class Person
的实例的大小为 sizeof(std::string) + sizeof(Dog)
,而 class Dog
的实例的大小为 sizeof(std::string) + sizeof(Dog)
尺寸为 sizeof(std::string) * 2
;所以 Person 的大小是 sizeof(std::string) * 3
(模对齐差异)
换句话说,C++ 中第一个 class 变量(相对于指针)所需的内存被分配 作为 实例的一部分,并且不是指针;这与 struct
s 的工作方式非常相似。事实上,在 C++ 中 class
和 struct
关键字之间确实没有实际区别,除了 class 默认是 private
而结构是public
.
除了这会导致一个无限的 space 对象(正如 Raphael 所解释的),编译器不会让这种情况发生,如 question 中所解释的那样。当你在 Dog
class 中使用它时,他不知道 Cat
class,所以它不会因为同样的原因而不起作用:
class B;
class A{
B b;
};
正如已经指出的那样,您不能直接或间接地定义一个没有间接寻址的成员的对象。
如果您只想使用 .
语法而不是 ->
语法,您可以使用引用而不是指针。例如:
// in Dog.h
class Cat;
class Dog {
public:
std::unique_ptr<Cat> catp;
Cat &c;
Dog ();
Dog (Cat &);
};
// in Cat.h
class Cat {
public:
std::unique_ptr<Dog> dogp;
Dog &d;
Cat ();
Cat (Dog &);
}
现在,在您的源代码中,您可以这样做:
#include "Dog.h"
#include "Cat.h"
Dog::Dog () : catp(new Cat(*this)), c(*catp) {}
Cat::Cat () : dogp(new Dog(*this)), d(*dogp) {}
Dog::Dog (Cat &cat) : c(cat) {}
Cat::Cat (Dog &dog) : d(dog) {}