【问题标题】:recursive definition in CPP [duplicate]CPP中的递归定义
【发布时间】:2010-11-29 02:29:49
【问题描述】:

我遇到了这样的问题:UPDATE

class A
{
public:
    A(){}
    int i;
    B b;
};

class B
{
public:
    B(){}
    int j;
    A a;
};

当我在一个 .h 文件中定义它时,它会报错。我认为问题在于递归定义。但是有人可以帮我解决这个问题吗?

  1. error C2146: syntax error : missing ';' before identifier 'b' c:\users\xingyo\documents\visual studio 2010\projects\cppalgo\recudef\test1.h 9 1 RecuDef

  2. error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\users\xingyo\documents\visual studio 2010\projects\cppalgo\recudef\test1.h 9 1 RecuDef

  3. error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\users\xingyo\documents\visual studio 2010\projects\cppalgo\recudef\test1.h 9 1 RecuDef

【问题讨论】:

  • 你到底想做什么?您给出的示例包含错误,让我们猜测。您真的是要在类A 中声明一个嵌套类class B 等吗?那不会是递归的。此外,如果您遇到错误请告诉我们该错误是什么。解决错误的第一步是了解错误。
  • 对不起,我已经更新了问题

标签: c++


【解决方案1】:

这在 C++ 中是不可能的。解释是编译器需要一个类的完整声明,而不仅仅是前向声明,才能将它用作另一个类的成员。它只需要一个类对象的大小

C++(和C)中的解决方法是使用指针引用作为其中一个类的成员。这样你就可以使用如下的前向声明:

class A; // forward declaration

class B {
    // ...
    A* pa;
};

class A { // full declaration
    // ...
    B b;
};

保持A 实例指向(或引用)的A 实例有效是您(而不是编译器或运行时)的责任。

【讨论】:

  • 请表现得体面一些,说出你投反对票的原因。
【解决方案2】:

你解决不了。这是没有意义的。您已将 A 定义为包含 B ,其中包含另一个 A ,其中包含另一个 B ……您不可能有意这样做。也许您需要使用指针或引用?

【讨论】:

  • 那些不是实例声明,这里根本没有递归。
  • 他们不是,但 OP 的编辑使它如此。
  • 这不仅没有意义,而且在物理上是不可能的。如果 OP 想要编译什么,它将创建一个无限大小的数据结构。 ;)
  • 这不仅在物理上不可能,在逻辑上也是不可能的。 IE。毫无意义。
【解决方案3】:

将代码拆分为 4 个文件,例如 A.h、A.cpp、B.h 和 B.cpp。

// A.h

class B;
class A {
public:
    A();
    B* b;
};

// A.cpp

#include "A.h"
#include "B.h"

A::A() : b(new B) {
}

// B.h

class A;
class B {
public:
    B(A* a_);
    A* a;
};

// B.cpp

#include "B.h"
#include "A.h"

B::B(A* a_) : a(a_) {
}

并以这种方式使用它们:

#include "A.h"
#include "B.h"

int main() {
    A a;
    B b(&a);

    // do logics

    return 0;
}

【讨论】:

    【解决方案4】:

    如果是递归问题。声明没有定义的类:

    class A;
    class B;
    
    class A
    {
       ...
    };
    
    class B
    {
       ...
    };
    

    见:http://www.gotw.ca/gotw/034.htm

    【讨论】:

    • 前向声明仅适用于指针和引用。
    • @Dima 不正确。它们也适用于类、结构和命名空间,可能也适用于联合。
    • @Dima:无论如何,他都必须使用指针或引用,这在物理上根本不可能让两个类或结构相互包含,因为结果将具有无限大小。
    • @EJP,你当然可以转发声明类、结构和命名空间。但是你不能声明一个只被前向声明的类或结构的对象,因为编译器还不知道它的大小。您只能声明指向前向声明的类或结构的指针或引用。
    • 我同意。这与“前向声明仅适用于指针和引用”有点不同,不是吗?
    【解决方案5】:

    在 C++ 中不能有这样的递归定义。在声明class A 的对象之前,必须完全定义A,以便编译器知道sizeof(A)。与 B 相同。但是,您可以通过使用指针来解决它。您可以声明一个指向class A 对象的指针,只需“承诺”在以后定义class A。这称为前向声明

    class B;  // forward declaration
    
    class A
    {
      B *b;
    };
    
    class B
    {
      A *a;
    };
    

    前向声明也适用于引用。

    【讨论】:

      猜你喜欢
      • 2014-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-13
      • 2021-07-20
      • 2013-05-06
      • 1970-01-01
      相关资源
      最近更新 更多