C++学习之路: 前向申明

引言:

  有种特殊情况,当两个类需要相互引用形成一个”环形“引用时,无法先定义使用。 这时候需要用到前向申明

但是前向申明的类不能实例化。

 1 #pragma once
 2
 3 #include "B.h"
 4 class A
 5 {
 6 public:
 7     A();
 8     ~A();
 9
10     B b_;
11 };
#pragma once
#include "A.h"
class B
{
public:
    B();
    ~B();

    A a_;
};

两个类互相包含编译的提示错误为:

1 1>------ 已启动生成:  项目: test, 配置: Debug Win32 ------
2 1>  B.cpp
3 1>g:\cpp\代码\test\test\a.h(10): error C2146: 语法错误: 缺少“;”(在标识符“b_”的前面)
4 1>g:\cpp\代码\test\test\a.h(10): error C4430: 缺少类型说明符 - 假定为 int。注意:  C++ 不支持默认 int
5 1>  A.cpp
6 1>g:\cpp\代码\test\test\b.h(9): error C2146: 语法错误: 缺少“;”(在标识符“a_”的前面)
7 1>g:\cpp\代码\test\test\b.h(9): error C4430: 缺少类型说明符 - 假定为 int。注意:  C++ 不支持默认 int
8 1>  正在生成代码...
9 ========== 生成:  成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

那么什么是前向申明呢?

#pragma once
#include "A.h"

class A;  //前向申明
class B
{
public:
    B();
    ~B();

    A a_;  //不可实例化
};

这样仍然是错误的,因为前向申明是不可实例化的。

编译提示:

1>------ 已启动生成:  项目: test, 配置: Debug Win32 ------
1>  B.cpp
1>g:\cpp\代码\test\test\a.h(10): error C2146: 语法错误: 缺少“;”(在标识符“b_”的前面)
1>g:\cpp\代码\test\test\a.h(10): error C4430: 缺少类型说明符 - 假定为 int。注意:  C++ 不支持默认 int
1>  A.cpp
1>g:\cpp\代码\test\test\b.h(11): error C2079: “B::a_”使用未定义的 class“A”
1>  正在生成代码...
========== 生成:  成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

很简单的处理,只需要使用指针即可。 经过试验 引用也可。

 1 #pragma once
 2 #include "A.h"
 3
 4 class A;
 5 class B
 6 {
 7 public:
 8     B();
 9     ~B();
10
11     A *a_;
12 };

嵌套类:Demo

 1 #include <iostream>
 2 using namespace std;
 3
 4
 5 class Outer
 6 {
 7     class Inner
 8     {
 9     public:
10         void fun()
11         {
12             cout << "Inner:Fun...." << endl;
13         }
14     };
15
16 public:
17     Inner obj_;
18     void fun()
19     {
20         cout << "Outer:fun..." << endl;
21         obj_.fun();
22     }
23
24 };
25
26 int main(void)
27 {
28     Outer o;
29     o.fun();
30 }

## 从作用域的角度看,嵌套类被影藏在外围类中,该类名只能在外围类中使用。如果在外围类的作用域中使用该类名时,需要加名字限定;

##嵌套类中的成员函数可以再它的类体外定义;

##嵌套类的成员函数对外围类的的成员没有访问权,反之亦然。

##嵌套类仅仅是语法上的嵌入

 1 #include <iostream>
 2 using namespace std;
 3
 4
 5 class Outer
 6 {
 7     class Inner
 8     {
 9     public:
10         void fun();
11     };
12
13 public:
14     Inner obj_;
15     void fun()
16     {
17         cout << "Outer:fun..." << endl;
18         obj_.fun();
19     }
20
21 };
22 void Outer::Inner::fun()
23 {
24     cout << "Inner:Fun...." << endl;
25 }
26
27 int main(void)
28 {
29     Outer o;
30     o.fun();
31 }

类体外申明只需要记住要加多个类名即可。

时间: 2024-10-08 09:29:38

C++学习之路: 前向申明的相关文章

我的python学习之路——前三天总结

1.基础入门1.1第一个Python代码 首先创建一个任意文件,结尾为py格式,然后在里面打入代码,在pycharm或者Python shell里面运行 print("钓鱼要钓刀鱼,刀鱼要到岛上钓") 1.2解释器编码 ascii,8位=1字节,一个英文字母是一个字节,py2的默认解释器编码就是ASCII码. Unicode,32位=4个字节,又叫万国码,一个字母或者汉字都是4个字节 utf-8,这是unicode的压缩版本,一个英文字母是一个字节,一个汉字是3个字节,py3的默认解释

一个女大学生的代码学习之路(二)

首先说一下,写这种文章是由于我在四月四日晚上,在手动搭建自己的第一个ssh项目的时候,遇到了一个配置的问题,怎么解决也弄不好,当时是四号晚上九点,我看了一眼表,我就想两个小时之内,我要是能搞定就算行了,但是其实,我搞到三点才OK(凌晨),那时候已经是五号了,转天是一家子去扫墓的时候,结果我居然以这种一个理由没有去,理由是我太累了么?我只是就是搭了一个架子,就是由于我的包太混乱了,导致不兼容,所以tomcat总也不启动,你可能认为好笑,这么简单一个问题怎么就费这多多时间呢,但是作为一个刚接触三框架

linux学习之路之磁盘管理和文件系统三

ext3文件系统和ext2文件系统的区别? 在某些时候,某个用户在linux系统上写入数据,这时系统正好断电或者系统核心出现错误,写入的数据仅有inode table和datablock而已,可能会导致之前写过的数据没有保存在磁盘上.而当系统重启后,系统可能会对没有保存的数据进行数据恢复.但是,由于系统并不知道是哪个文件不完整,因此会遍历整个文件系统中inode,来查看block是否完整.不过,当某个文件的数据太大时,数据的恢复时间可能会比较长,而这对于服务器来说是不利的.所以在这种情况下,也就

linux学习之路之vim编辑器的使用

本章将介绍vim编辑器的使用 vim编辑器是vi编辑器的增强版 vim是一种全屏的编辑器,是一种模式化的编辑器,之所以称为模式化的编辑器,因为vim有多种模式. 接下来将介绍vim主要的三种模式: 编辑模式(也叫命令模式):在该模式下你可以完成字符串跳转,字符串删除,翻屏操作等操作 输入模式:在该模式下输入的任何字符都会保存在该文件中,作为文件的一部分 末行模式:在该模式下,可以实现字符串搜索,字符串替换等操作 vim编辑器的三种模式之间的相互转换 模式转换: 编辑模式-->输入模式 i:在当前

linux学习之路及文本查看和文本处理命令

这一篇主要介绍几个常用的文本查看命令和文本处理命令. 首先介绍文本查看命令 cat:用于连接文件并显示 说明:当只有一个文件时,则用于查看文件内容:当有多个文件时,cat命令会将这些文件连接起来,在一起显示出来 语法格式:cat [option] FILE... -n:显示内容的时候把行号显示出来 -E:显示每一行的结束符$符(默认不显示) tac:也是用于显示文件内容,只不过他是将文件的内容倒过来显示,与cat相反 -n:显示行号 -E:显示每一行结尾的结束符$ 分屏操作命令 more与les

STM32学习之路-LCD(2)&lt;LCD初始化&gt;

这些天一直在研究LCD的初始化函数,因为不过是用IO口模拟时序还是用FSMC来驱动LCD,都必须要弄好LCD的初始化 其实LCD的初始化就是跟着LCD IC的datasheet来写寄存器,大部分都使用上面的默认值,网上有很多修改的例子,这里就不 放出来了.但是我想写下一些比较重要的东西. 这是从网上下载来的一个文件的前半部分: 当然,别的型号的IC也是有这些东西的,不过可能有些地址不同而已. R0,这个命令有两个功能,如果对它写,则最低位为OSC,用于开启和关闭振荡器.而如果对它读操作, 则返回

zz 游戏程序员的学习之路(中文版)

游戏程序员的学习之路(中文版) Milo Yip · 1 天前 感谢 @楚天阔(tkchu)编写脚本及整理中文译本数据,自动从英文版生成中文版,SVG / PDF 版本中的书籍图片现在链接至豆瓣页面. Github miloyip/game-programmer 检视/下载中文版 SVG / PDF 「真诚赞赏,手留余香」 赞赏 15 人赞赏 程序员游戏开发书籍推荐 分享 举报 977 文章被以下专栏收录 Milo的编程 进入专栏 97 条评论 写下你的评论 trycatch 这是劝退吧...

开始了大概三四天的Rails学习之路

最近因为一位极光推送朋友,我开始了大概三四天的Rails学习之路,最终达到的水平是可以比较轻松地做出大部分功能,然后自我感觉可以自如地按照Rails的设计思想去思考.由于编程的日益流行,我结识了越来越多非计算机系的学生出于爱好开始写代码,但是其中的大部分人也许在用着一些错误的学习方式来学习编程,为了避免大家再继续走弯路,在这篇文章中,我会介绍下一个初学者要如何学习Rails. 1. 为何而学,目标是什么? 今天和朋友在走路时,谈到要如何学习Rails,我问的第一个问题是,你为什么要学习Rails

jQuery学习之路(四)之过滤选择器

今天是第四课主要学习过滤选择器 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>lesson4 过滤选择器</title> <link rel="stylesheet" type="text/css" href="css/lesson.css" ></link>