c++ 类前置声明【转】
【转自 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++ 类前置声明【转】的更多相关文章
- 【C++】类前置声明范例
• 在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration).下面的程序中,带注释的那行就是类B的前置说明.这是必须的,因为类A中用到了类B,而类B的声明出现在类A的后面 ...
- C++ 类声明 类前置声明范例
转载自http://www.cnblogs.com/staring-hxs/p/3244251.html 在编写C++程序的时候,偶尔需要用到前置声明(Forward declaration).下面的 ...
- C++类前置声明
cpp前置声明: 前置声明只能作为指针或引用,不能定义类的对象,也不能调用对象中的方法. 详见:https://www.cnblogs.com/dobben/p/7440745.html
- Qt class 前置声明
转载:https://www.cnblogs.com/ycbeginner/p/9403976.html 在Qt开发项目中,经常会用到各种库,但是一般在.h文件中进行某类型变量定义时,都会对其类型的c ...
- C++ 类的前置声明
http://www.2cto.com/kf/201311/260705.html 今天在研究C++”接口与实现分离“的时候遇到了一个问题,看似很小,然后背后的东西确值得让人深思!感觉在学习的过 ...
- 【C/C++开发】C++之enum枚举量声明、定义、使用与枚举类详解与枚举类前置类型声明
众所周知,C/C++语言可以使用#define和const创建符号常量,而使用enum工具不仅能够创建符号常量,还能定义新的数据类型,但是必须按照一定的规则进行,下面我们一起看下enum的使用方法. ...
- C++中头文件相互包含与前置声明
一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题.假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中, ...
- C++ 前置声明 和 包含头文件 如何选择
假设有一个Date类 Date.h class Date { private: int year, month, day; }; 如果有个Task类的定义要用到Date类,有两种写法 其一 Task1 ...
- C++_前置声明
为什么要有前置声明? eg: -定义一个类 class A,这个类里面使用了类B的对象b,然后定义了一个类B,里面也包含了一个类A的对象a,就成了这样: //a.h #include "b. ...
随机推荐
- (转)在公司的局域网使用git或github 设置代理
目录 [hide] 1 生成SSH Key 2 git使用http访问 3 git使用ssh进行访问 在公司这样的局域网环境中,向要走网络必须走HTTP代理出去.不能直接访问外面的服务,所以这样安全了 ...
- Android Handler机制 (一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理 ,但是 每个线程中最多只有一个Looper,肯定也就一个MessageQuque)
转载自http://blog.csdn.net/stonecao/article/details/6417364 在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长 ...
- 使用appledoc 生成技术API文档具体解释
一. 首先安装 appledoc 第一步:使用终端命令进行下载安装 git clone git://github.com/tomaz/appledoc.git cd ./appledoc sudo s ...
- 7月目标 socket , 一致性哈希算法 ; mongodb分片; 分布式消息队列; 中间件的使用场景
分布式的基础:一致性哈希 路由算法的一致性hash http://www.jiacheo.org/blog/174 http://www.tuicool.com/articles/vQVbmai ...
- Keepalived + Nginx + Tomcat 的高可用负载均衡架构搭建
Keepalived + Nginx + Tomcat 的高可用负载均衡架构搭建 Nginx 是一个高性能的 HTTP反向代理服务器 Keepalived 是一个基于VRRP协议来实现的LVS服务高可 ...
- CentOS6.8下安装MySQL5.6
一:卸载旧版本 使用下面的命令检查是否安装有MySQL Server rpm -qa | grep mysql 有的话通过下面的命令来卸载掉 rpm -e mysql //普通删除模式 rpm -e ...
- 使用Spring.NET的IoC容器
使用Spring.NET的IoC容器 0. 辅助类库 using System; using System.Collections.Generic; using System.Linq; using ...
- sublime text3支持Vue语法高亮显示
1.下载文件链接: 或https://github.com/vuejs/vue-syntax-highlight 解开压缩包vue-syntax-highlight-master,其内所有文件备用. ...
- c/c++ 代码中使用sse指令集加速
使用SSE指令,首先要了解这一类用于进行初始化加载数据以及将暂存器的数据保存到内存相关的指令, 我们知道,大多数SSE指令是使用的xmm0到xmm8的暂存器,那么使用之前,就需要将数据从内存加载到这些 ...
- java rpc
一.简介 Hessian和Burlap是由Caucho Technology提供的基于HTTP协议的轻量级远程服务解决方案.他们都致力于借助尽可能简单那的API和通信协议来简化Web服务. He ...