【转自 here

在编写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类的构造函数中,采用初始化列表的方式初始化,否则也会出错。关于这点

见:

特殊数据类型成员变量的初始化

c++ 类前置声明【转】的更多相关文章

  1. 【C++】类前置声明范例

    • 在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration).下面的程序中,带注释的那行就是类B的前置说明.这是必须的,因为类A中用到了类B,而类B的声明出现在类A的后面 ...

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

    转载自http://www.cnblogs.com/staring-hxs/p/3244251.html 在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration).下面的 ...

  3. C++类前置声明

    cpp前置声明: 前置声明只能作为指针或引用,不能定义类的对象,也不能调用对象中的方法. 详见:https://www.cnblogs.com/dobben/p/7440745.html

  4. Qt class 前置声明

    转载:https://www.cnblogs.com/ycbeginner/p/9403976.html 在Qt开发项目中,经常会用到各种库,但是一般在.h文件中进行某类型变量定义时,都会对其类型的c ...

  5. C++ 类的前置声明

    http://www.2cto.com/kf/201311/260705.html    今天在研究C++”接口与实现分离“的时候遇到了一个问题,看似很小,然后背后的东西确值得让人深思!感觉在学习的过 ...

  6. 【C/C++开发】C++之enum枚举量声明、定义、使用与枚举类详解与枚举类前置类型声明

    众所周知,C/C++语言可以使用#define和const创建符号常量,而使用enum工具不仅能够创建符号常量,还能定义新的数据类型,但是必须按照一定的规则进行,下面我们一起看下enum的使用方法. ...

  7. C++中头文件相互包含与前置声明

    一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题.假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中, ...

  8. C++ 前置声明 和 包含头文件 如何选择

    假设有一个Date类 Date.h class Date { private: int year, month, day; }; 如果有个Task类的定义要用到Date类,有两种写法 其一 Task1 ...

  9. C++_前置声明

    为什么要有前置声明? eg: -定义一个类 class A,这个类里面使用了类B的对象b,然后定义了一个类B,里面也包含了一个类A的对象a,就成了这样: //a.h #include "b. ...

随机推荐

  1. 【转载】C#反射机制详解

    反射的定义:审查元数据并收集关於它的类型信息的能力,元数据(编辑后的基本数据单元)就是一大堆表,编译器会创建一个类定义表,一个字段定义表,一个方法定义表等,System.Reflection命名空间包 ...

  2. unity------------------------------transform.forward与Vector.forward的区别

    在unity3d中有2个forward,一个是vector3.forward和transform.forward,这两个forward其实完全不一样.他们之间的区别主要体现在在不同坐标系时的反映上. ...

  3. CentOS 6.x安装配置MongoDB 3.4.x

    说明: 操作系统:CentOS 5.X 64位 IP地址:192.168.21.128 实现目的: 安装配置MongoDB数据库 具体操作: 一.关闭SElinux.配置防火墙 1.vi /etc/s ...

  4. python_django_sae入口配置

    --index.wsgi import sys import os.path os.environ['DJANGO_SETTINGS_MODULE'] = 'APPNAME.settings' sys ...

  5. EF5+MVC4系列(5) 删除的方法 1:系统推荐的先查询后remove删除的方法 2:自己new一个包含主键的类,然后 attach附加 remove删除;3:使用db.Entry 修改状态删除4:EntityState的几种状态

      我们还是以订单表为例   1:系统推荐的方法,先查询出来,然后调用remove方法进行删除 我们删除id大于等于4的 static void Main(string[] args) { Delet ...

  6. Wings 3D

    Wings 3D 编辑 Wings 3D 是一个开源的三维计算机图形软件.使用翼边数据库.注重于多边形建模,构思取与 Izware 的 Nendo 和 Mirai.支持多种操作系统,包括 Linux. ...

  7. 多个IoC容器适配器设计及性能测试(Castle.Windsor Autofac Spring.Core)

    [转]多个IoC容器适配器设计及性能测试和容器选择 1. 采用的IoC容器和版本 Autofac.2.6.3.862 Castle.Windsor.3.1.0 Spring.Core.2.0.0 2. ...

  8. 简单介绍Linux下安装Tomcat的步骤

    Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成.由于有了Sun的参与和支持,最新的 ...

  9. VS2010 工程设置

       本篇文章的主要内容转载自 http://blog.csdn.net/waitforfree/article/details/8622059 ,感谢博主的辛苦劳动.此处,对比较重要的部分,进行进一 ...

  10. [WPF打印]WPF 文档元素(Run TextBlock Paragraph)的文字对齐方式

    最近开发WPF程序,需要打印,用到了FlowDocument(这相当于有了打印模版,而且可以随时修改,真的是挺方便的).可是在输出表格形数据(这种情况恐怕是大多数~)时遇到了点儿麻烦. 由于Table ...