如何在 C++ 中创建两个相互用作数据的类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4964482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:01:47  来源:igfitidea点击:

How to create two classes in C++ which use each other as data?

c++classpointersheader-files

提问by Steve Johnson

I'm looking to create two classes, each of which contains an object of the other class type. How can I do this? If I can't do this, is there a work-around, like having each class contain a pointerto the other class type? Thanks!

我希望创建两个类,每个类都包含另一个类类型的对象。我怎样才能做到这一点?如果我不能这样做,是否有解决方法,例如让每个类都包含一个指向其他类类型的指针?谢谢!

Here's what I have:

这是我所拥有的:

File: bar.h

文件:bar.h

#ifndef BAR_H
#define BAR_H
#include "foo.h"
class bar {
public:
  foo getFoo();
protected:
  foo f;
};
#endif

File: foo.h

文件:foo.h

#ifndef FOO_H
#define FOO_H
#include "bar.h"
class foo {
public:
  bar getBar();
protected:
  bar b;
};
#endif

File: main.cpp

文件:main.cpp

#include "foo.h"
#include "bar.h"

int
main (int argc, char **argv)
{
  foo myFoo;
  bar myBar;
}

$ g++ main.cpp

$ g++ main.cpp

In file included from foo.h:3,
                 from main.cpp:1:
bar.h:6: error: ‘foo' does not name a type
bar.h:8: error: ‘foo' does not name a type

回答by templatetypedef

You cannot have two classes directly contain objects of the other type, since otherwise you'd need infinite space for the object (since foo has a bar that has a foo that has a bar that etc.)

你不能让两个类直接包含另一种类型的对象,否则你需要为对象提供无限空间(因为 foo 有一个 bar 有一个 foo 有一个 bar 等等)

You can indeed do this by having the two classes store pointers to one another, though. To do this, you'll need to use forward declarationsso that the two classes know of each other's existence:

不过,您确实可以通过让两个类存储彼此的指针来做到这一点。为此,您需要使用前向声明,以便两个类知道彼此的存在:

#ifndef BAR_H
#define BAR_H

class foo; // Say foo exists without defining it.

class bar {
public:
  foo* getFoo();
protected:
  foo* f;
};
#endif 

and

#ifndef FOO_H
#define FOO_H

class bar; // Say bar exists without defining it.

class foo {
public:
  bar* getBar();
protected:
  bar* f;
};
#endif 

Notice that the two headers don't include each other. Instead, they just know of the existence of the other class via the forward declarations. Then, in the .cpp files for these two classes, you can #includethe other header to get the full information about the class. These forward declarations allow you to break the reference cycle of "foo needs bar needs foo needs bar."

请注意,这两个标题不包含彼此。相反,他们只是通过前向声明知道另一个类的存在。然后,在这两个类的 .cpp 文件中,您可以#include通过另一个头文件获取有关该类的完整信息。这些前向声明使您可以打破“foo 需要 bar 需要 foo 需要 bar”的引用循环。

回答by EboMike

That doesn't make sense. If A contains B, and B contains A, it would be infinite size. Imagine putting having two boxes and trying to put both into each other. Doesn't work, right?

那没有意义。如果 A 包含 B,而 B 包含 A,则它将是无限大小。想象一下把两个盒子放在一起,然后试着把它们放在一起。不起作用,对吧?

Pointers work though:

指针虽然有效:

#ifndef FOO_H
#define FOO_H

// Forward declaration so the compiler knows what bar is
class bar;

class foo {
public:
  bar *getBar();
protected:
  bar *b;
};
#endif

回答by TrisT

Right so just to add,

没错,只是补充一下,

the above methods will only allow you to have pointers to said classes.

上述方法只允许您拥有指向所述类的指针。

In my travels I've found that a function that creates an instance of a class that has a pointer to it can also be done (code image, actual code at the end):

在我的旅行中,我发现创建一个具有指向它的指针的类的实例的函数也可以完成(代码图像,最后是实际代码)

code and running

代码和运行

Here you include the header from the class you're "spawning", so that the compiler has actual information about it and can thus create it.

在这里,您包括来自您正在“生成”的类的头文件,以便编译器拥有有关它的实际信息,从而可以创建它。

Of course this also allows you to have an instance of B inside of A (code image, actual code at the end):

当然,这也允许您在 A 内部拥有 B 的实例(代码图像,最后是实际代码)

b inside of a kappa

b inside of a kappa

You can probably also think of some other kewl stuff, gn.

您可能还可以想到其他一些 kewl 的东西,gn。



Non-image Code

非图像代码

Example 1

示例 1

a.h:

#pragma once

#include "b.h"

struct A {
    char aye, beye, ceye;
    B createB(unsigned val);
};

a.cpp:

a.cpp:

#include "a.h"

B A::createB(unsigned val){
    return {69, this};
}

b.h:

#pragma once

struct A;

struct B {
    unsigned ellel;
    A* dad;
    B& printOurEllel();
};

b.cpp:

b.cpp:

#include <stdio.h>
#include "b.h"

B& B::printOurEllel(){
    printf("ellel: %d\n", this->ellel);
    return *this;
}

main:

主要

#include <stdio.h>

#include "a.h"
#include "b.h"


int main() {
    A elgay = { 1, 2, 3 };
    printf("%d\n", elgay.createB(69).printOurEllel().dad->beye);
    getchar();
}

result:

结果

ellel: 69
2

Example 2

示例 2

a.h:

#pragma once

#include "b.h"

struct A {
    char aye, beye, ceye;
    B yeetos;
};

b.h:

#pragma once

struct A;

struct B {
    unsigned ellel;
    A* dad;
    B& printOurEllel();
};

b.cpp:

b.cpp:

#include <stdio.h>
#include "b.h"

B& B::printOurEllel(){
    printf("ellel: %d\n", this->ellel);
    return *this;
}  

main:

主要

#include <stdio.h>

#include "a.h"
#include "b.h"


int main() {
    A elgay = { 1, 2, 3, {69, &elgay} };
    printf("%d\n", elgay.yeetos.printOurEllel().dad->beye);
    getchar();
}

result:

结果

ellel: 69
2