【问题标题】:Forward Declaration of Class, Function类、函数的前向声明
【发布时间】:2011-01-07 16:59:13
【问题描述】:

当函数的前向声明在源文件 (.cpp) 中起作用时,为什么对类不起作用?

谢谢。

// main.cpp

void forwardDeclaredFunction() ; // This is correct 

class One ; // Why this would be wrong 

int One:: statVar = 10 ;

void
One :: anyAccess() {

 std::cout << "\n statVar:\t " << statVar ;
 std::cout << "\n classVar:\t" << classVar ;
}

class One {

 public:
  void anyAccess() ;
  static int statVar ;

 private:
  int  classVar ;

} ;


int main (int argc, char * const argv[]) {

 One *obj = new One ;

        return 0;
}

void forwardDeclaredFunction() {
}

【问题讨论】:

  • class One; 是前向类声明的正确语法。你到底得到了什么编译器错误消息?
  • 错误:不完整类型结构一的使用无效;我在 Mac 上运行

标签: c++ visual-c++


【解决方案1】:

前向声明也适用于类:

class Foo;

class Bar {
public:
    Foo *myFoo; // This has to be a pointer, thanks for catching this!
};

class Foo {
public:
    int value;
};

上面的代码显示了 Foo 类的前向声明,在另一个类(Bar)中使用了 Foo* 类型的变量,然后是 Foo 类的实际定义。只要在使用它的代码之前实现它们,C++ 就不会在意你是否留下未实现的东西。定义指向某种类型对象的指针并不是“使用它的代码”。

快速,肮脏的回复,但我希望它有所帮助。

编辑:声明未实现的类的非指针变量将不会像回复所述的那样编译。这样做正是我所说的“使用它的代码”。在这种情况下,只要调用 Bar 构造函数,就会调用 Foo 构造函数,因为它有一个 Foo 类型的成员变量。由于编译器不知道您计划稍后实现 Foo,因此它会抛出错误。对不起我的错误;)。

【讨论】:

  • AFAIK,前向声明不允许您拥有如此声明的类的对象——只有指针,可能还有引用。在您的示例中,编译器尚不知道sizeof(Foo),因此无法定义Bar
  • 由于 OP 的代码失败的相同原因,这不会编译:您在 Foo 的完整结构已知之前使用它(gcc 会告诉您“字段 'myFoo' 的类型不完整”)
  • 别忘了你也可以声明一个引用,只需要前向声明它的类型,例如:const Foo&amp; myFoo
【解决方案2】:

前向声明class One; 允许您引用类本身,但不能引用它的任何成员。您必须将类成员的所有定义放在类的完整声明之后。 (当然也可以在里面。)

【讨论】:

    【解决方案3】:

    将类的成员声明放在成员实现之前。

    class One {
    
     public:
      void anyAccess() ;
      static int statVar ;
    
     private:
      int  classVar ;
    
    } ;
    
    int One:: statVar = 10 ;
    
    void
    One :: anyAccess() {
    
     std::cout << "\n statVar:\t " << statVar ;
     std::cout << "\n classVar:\t" << classVar ;
    }
    

    【讨论】:

      【解决方案4】:

      您在 int One:: statVar = 10 ; 而不是前向声明中收到错误消息,这很好。

      编译器需要知道类的完整定义,然后才能定义这样的静态成员 - 前向声明是不够的(它需要能够从类定义中确认类型是正确的)。

      您需要将静态属性定义移到类定义下方。

      【讨论】:

        【解决方案5】:

        编译器从头到尾读取内容,并在执行过程中生成代码。 (有些编译器可能不这样做,但它们应该表现得好像它们那样。)但是在定义类之前,编译器不知道One::statVarOne::anyAccess应该存在,或者函数是虚拟的还是静态的, 或者是什么。它需要知道这些东西才能生成代码。

        【讨论】:

          【解决方案6】:

          当您创建 2 个类和一个函数时,可以将数据从一个类访问到另一个类 那么它是一个朋友功能

          前言声明用于知道下一个类

          类 abc;

          类 xyz

          {

          数据成员;

          公开:

          朋友 void getdata();

          其他成员函数

          }

          类 abc

          {

          数据成员

          公开:

          朋友 void getdata();

          }

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-08
            • 2012-03-08
            相关资源
            最近更新 更多