C++不完整的类型
今天写C++primer 5th中文版第422页的程序时,出现了”不允许使用不完整的类型“的错误,下面我就用类A 与 类B 作为代表,重现一下该错误,并且提出解决方案。
一、带问题的类设计A:
1、类A放在A.h 与 A.cpp中
2、由于B需要访问A的私有成员,故声明B是其友元类
3、A中需要利用自身作为参数去创建一个新的B类实例。
代码如下:A.cpp中就是一个空的析构函数的实现。。。没什么,我把主要实现都写在了A.h中
#pragma once
#include<iostream> class B; // 声明B 从而能够在下文声明为友元类
class A
{
public:
friend class B; // 声明B为友元类
A(int a) :data(a){} B Pirnt() // 打印一行文字并且调用B的构造函数:B(A &a, int secParam = 5)创建一个B的实例
{
std::cout << "hehe " << std::endl;
return B(*this);
}
~A();
private:
int data;
};
二、带问题的类设计B
1、B 接受一个A 引用参数,达成构造B的目的
同样的,B.cpp中也是一个空的构造函数与一个空的析构函数,下面展示的是B.h中的代码:
#pragma once
#include "A.h"
class B
{
public:
B(A &a, int secParam = ) :data(a.data){}
B();
~B(); private:
int data;
};
三、问题提示:
在A.h的第11 与 14行使用B的地方提示”B不是完整的数据类型“
四、分析
首先,我们需要在类A中将B声明为友元类,此时类B尚未定义,故仅在class A前面声明了class B;然后在此利用B进行代码编写,但是带来了问题:
这种声明叫做 前向声明,它在声明之后,定义之前的这段时间,它都是不完整的,对于类A中的代码来讲,他们不知道B什么时候定义,所以编译器直接认为B是不完整的。。。
如果分别在A.h与B.h中包含对方的头文件,又造成了循环包含。
五、解决方案。
1、将A B写在一个头文件中
2、声明A,定义B
3、定义A
代码:
A.h
#pragma once
#include<iostream>
class A; // 声明A class B
{
public:
B(A &a, int secParam = ); // 只可声明,不能在此处定义,具体定义在B.cpp中写
~B(); private:
int data;
}; class A
{
public:
friend class B; // 声明B为友元类
A(int a) :data(a){} B Pirnt() // 打印一行文字并且调用B的构造函数:B(A &a, int secParam = 5)创建一个B的实例
{
std::cout << "hehe " << std::endl;
return B(*this);
}
~A();
private:
int data;
};
B.cpp
#include "A.h"
B::B(A &a, int secParam) :data(a.data)
{
} B::~B()
{
}
对于A.cpp,还是空的构造函数与析构函数
原因:
1、上文说道在类声明与定义之间的时间内,其是不完整的,不可使用的,但是 可以定义指向这种类型的指针和引用,可以声明(不能定义)以不完整类型作为参数或者返回类型的函数。
故,可以先在B中的构造函数里使用 A& 这个参数.
不过使用A&作为参数的那个构造函数的实现(定义)需要在cpp中写,因此执行到CPP的时候,A已经是完整的了。
2、 执行到A时,B的各成员声明已经完整。
C++不完整的类型的更多相关文章
- 如何在C++中获得完整的类型名称(RTTI的typeid在不同平台下有不同的输出值表达,自建类改进了RTTI丢失的信息)
		Wrote by mutouyun. (http://darkc.at/cxx-get-the-name-of-the-given-type/) 地球人都知道C++里有一个typeid操作符可以用 ... 
- 怎样在C++中获得完整的类型名称
		Wrote by mutouyun. (http://darkc.at/cxx-get-the-name-of-the-given-type/) 地球人都知道C++里有一个typeid操作符能够用来获 ... 
- VS2013 :IntelliSense:  不允许使用不完整的类型
		出现上述情况,一般是存在对应的头文件,但是没有引用造成的. 引用的时候要注意头文件的顺序, 本项目中的头文件一般先引入,也就是用双引号#include "xxx.h",然后是系统中 ... 
- C语言的不完整类型和前置声明(转)
		声明与定义(Declaration and Definition) 开始这篇文章之前,我们先弄懂变量的declaration和definition的区别,即变量的声明和定义的区别. 一般情况下,我们这 ... 
- C#中类型分析中的常见问题 Type -  转
		http://www.cnblogs.com/yuanyuan/archive/2012/08/16/2642281.html 写代码的时候经常需要分析已有类型的信息例如:分析现有类型自动生成类, 或 ... 
- sizeof(extern类型数组)
		error: #70: incomplete type is not allowed 用sizeof计算数组大小,编译器提示不允许使用不完整的类型.在keil上编译直接报错,拿到vs2010上编译可 ... 
- C#实现完整的防盗自制监控系统
		在您的手机中通知您家中的入侵者,并拍摄他们的照片 介绍 在本文中,我将展示一些DIY东西,用于安装监控系统,检测家中的入侵者,拍摄照片并通过手机通知您,必要时可以打电话给警察并提供照片以便快速识别 ... 
- Spring IOC(七)类型推断
		Spring IOC(七)类型推断 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring 容器中可以根据 bean ... 
- Android源码大放送之material design类型
		本文转载自:http://www.apkbus.com/android-243232-1-1.html 鉴于大家对源码的渴望,就算自己辛苦一点也要满足大家的需求,查看了几百个源码之后终于筛选出了这些精 ... 
随机推荐
- window8.1中用户的管理员权限的提升方法
			1.使用命令netplwiz 2.点击确定后出现如下所示的内容,选择待修改的用户 3.然后点击属性,出现如图的内容 在上图中选中管理员左侧的单选按钮便可以了,将当前用户提升为管理员账户. 
- 【HTTP】POST 与 PUT 方法区别
			1. POST 用于向服务端发送数据,常用于表单数据提交: PUT 用于向服务器上的资源(如文件)中存储数据: 2. 302 303 307 状态码区别 他们都是重定向(临时重定向 p.s 301 ... 
- React生命周期和虚拟DOM
			一.虚拟DOM 1.React并不直接操作DOM,React中的render方法,返回一个DOM描述,React能够将这个DOM描述与内存中的表现进行比较,然后以最快的方式更新浏览器 2.React实 ... 
- javascript各种兼容性问题,不断更新
			ie6-ie8 不支持textContent支持innerTextchrome 支持textContent innerTextfireFox 仅支持textContent不支持innerTe ... 
- aspxgridView,Repeater增加自动序号列
			第一种方式,直接在Aspx页面GridView模板列中.这种的缺点是到第二页分页时又重新开始了. <asp:TemplateField HeaderText="序号" Ins ... 
- pb中创建连接webservice对象实例方法
			try soapConnection conn // Define SoapConnectionHospitalServiceSoap in_hhzswebser // Declare proxyin ... 
- 【Spring 1】Spring简介
			一.Spring简介 首先,Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途不仅仅限于服务器端的开 ... 
- [JFinal 1] JFinal和SSH中使用拦截器的对比
			导读:先前在做.NET项目时,拦截的功能主要是依靠缓存session来实现.当需要跳转到某个页面,使用某个功能查询一些数据时,会根据session中的用户值来判断是否已经正常登录,如果没有,则重定向到 ... 
- ionic localstorage
			angular.module('locals',[]) .factory('ls', ['$window', function($window) { return { set: function(ke ... 
- C#  发送邮件方法
			发送邮件所用的核心知识点 微软封装好的MailMessage类:主要处理发送邮件的内容(如:收发人地址.标题.主体.图片等等) 微软封装好的SmtpClient类:主要处理用smtp方式发送此邮件的配 ... 
