C++ 类声明 类前置声明范例

转载自http://www.cnblogs.com/staring-hxs/p/3244251.html

在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration)。下面的程序中,带注释的那行就是类B的前置说明。这是必须的,因为类A中用到了类B,而类B的声明出现在类A的后面。如果没有类B的前置说明,下面的程序将不同通过编译,编译器将会给出类似“缺少类型说明符”这样的出错提示。

代码一:
// ForwardDeclaration.h
#include <iostream>
using namespace std;
class B;             // 这是前置声明(Forward declaration)
class A
{
private:
         B* b;
public:
         A(B* b):b(b){}
};

class B
{
};
// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
         B* b = new B();
         A* a = new A(b);
         delete a;
         delete b;
         return 0;
}

上面程序可以顺利编译和运行(几乎没有做什么,也没有输出)。

是不是有了前置说明就万事大吉了呢?我们看看下面的代码(带阴影部分的代码是新增加的):

代码二:

// ForwardDeclaration.h
#include <iostream>
using namespace std;
class B;             // 这是前置声明(Forward declaration)
class A
{
private:
         B* b;
public:
         A(B* b):b(b){}
        void someMethod()
         {
            b->someMethod();                                                  // (1)
         }
};

class B
{
public:
      void someMethod()
       {
          cout << "something happened..." << endl;
       }
};
// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
         B* b = new B();
         A* a = new A(b);
    a->someMethod();
    delete a;
    delete b;
    return 0;
}

一编译,发现代码(1)处出错。出错提示往往包括(不同的编译器给出的提示会有所不同):

1. 使用了未定义的类型B;

2. “->somemethod”的左边必须指向类/结构/联合/泛型类型

原因:

1. (1)处使用了类型B的定义,因为调用了类B中的一个成员函数。前置声明class B;仅仅声明了有一个B这样的类型,而并没有给出相关的定义,类B的相关定义,是在类A后面出现的,因此出现了编译错误;

2. 代码一之所以能够通过编译,是因为其中仅仅用到B这个类型,并没有用到类B的定义。

解决办法是什么?

将类的声明和类的实现(即类的定义)分离。如下所示:

// ForwardDeclaration.h   类的声明
#include <iostream>
using namespace std;
class B;             // 这是前置声明(Forward declaration)
class A
{
private:
         B* b;
public:
        A(B* b);
void someMethod();
};

class B
{
public:
void someMethod();
};
// ForwardDeclaration.cpp        类的实现
#include "ForwardDeclaration.h"
A::A(B* b):b(b)
{

}

void A::someMethod()
{
    b->someMethod();
}

void B::someMethod()
{
    cout << "something happened..." << endl;
}
// Main.cpp
#include "ForwardDeclaration.h"
int main(int argc, char** argv)
{
         B* b = new B();
         A* a = new A(b);
         a->someMethod();
     delete a;
         delete b;
     return 0;
}

结论:

前置声明只能作为指针或引用,不能定义类的对象,自然也就不能调用对象中的方法了。

而且需要注意,如果将类A的成员变量B* b;改写成B& b;的话,必须要将b在A类的构造函数中,采用初始化列表的方式初始化,否则也会出错。关于这点

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C++ 中,可以使用声明前置(forward declaration)来解决互相依赖的之间的编译问题。声明前置可以让编译器知道某个的存在,而无需包含该的头文件。 具体来说,如果一个 A 依赖于另一个 B,而 B 又依赖于 A,那么在定义这两个时,就会产生循环依赖的问题。此时,我们可以使用声明前置来解决这个问题。 例如,假设有两个 `ClassA` 和 `ClassB`,它们互相依赖,可以这样来声明前置: ```cpp // ClassA.h 文件 #pragma once // 前置声明 ClassB class ClassB; class ClassA { public: void func(ClassB* b); }; // ClassB.h 文件 #pragma once // 前置声明 ClassA class ClassA; class ClassB { public: void func(ClassA* a); }; ``` 在上面的代码中,我们使用了 `class ClassB;` 和 `class ClassA;` 来声明前置,而不是包含的头文件。这样,编译器就能够知道这两个的存在,从而解决了循环依赖的问题。 需要注意的是,如果使用了声明前置,那么只能在函数参数、函数返回值或者指针成员变量等地方使用这个。如果需要使用该的具体实现,还需要包含该的头文件。例如,在 `ClassA.cpp` 文件中实现 `ClassA` 的成员函数时,需要包含 `ClassB.h` 头文件: ```cpp // ClassA.cpp 文件 #include "ClassA.h" #include "ClassB.h" void ClassA::func(ClassB* b) { // 使用 ClassB 的具体实现 } ``` 总之,声明前置可以解决互相依赖的之间的编译问题,提高代码的可读性和可维护性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值