嵌套类,PIMPL
body, table{font-family: 微软雅黑; font-size: 10pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}
#include <iostream>
using namespace std;
int x = 100; //定义性声明,全局int型变量x
int z = 200; //定义性声明,全局int型变量z
class Example //Example类定义
{
int x; //默认为private的成员列表
int y;
public:
Example(int xp = 0, int yp = 0) //构造函数
{
x = xp;
y = yp;
}
void print(int x) //成员函数print,形参为x
{
cout << "传递来的参数: " <<x << endl;
//形参x覆盖掉了成员x和全局变量x
cout << "成员x: " << (this->x) << ", 成员y: " << y << endl;
//此处的y指的是成员y,如果要访问成员x,可使用this指针
cout << "除了this指针外,还可以使用类名::的形式:" << endl;
cout << "成员x: " << Example::x << ", 成员y: " << y << endl;
//或使用类名加作用域限定符的形式指明要访问成员x
cout << "全局x: " << (::x) << endl;
//访问全局变量x
cout << "全局z: " << z << endl;
//没有形参、数据成员对全局变量z构成屏蔽,直接访问z即可
}
};
|
int main()
{
Example ex1; //声明一个Example类的对象ex1
ex1.print(5); //调用成员函数print()
return 0;
} |
在一个类的内部定义另一个类,我们称之为嵌套类(nested class),或者嵌套类型。之所以引入这样一个嵌套类,往往是因为外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现。
虽然嵌套类在外围类内部定义,但它是一个独立的类,基本上与外围类不相关。它的成员不属于外围类,同样,外围类的成员也不属于该嵌套类。嵌套类的出现只是告诉外围类有一个这样的类型成员供外围类使用。并且,外围类对嵌套类成员的访问没有任何特权,嵌套类对外围类成员的访问也同样如此,它们都遵循普通类所具有的标号访问控制。
若不在嵌套类内部定义其成员,则其定义只能写到与外围类相同的作用域中,且要用外围类进行限定,不能把定义写在外围类中。例如,嵌套类的静态成员就是这样的一个例子。
前面说过,之所以使用嵌套类的另一个原因是达到底层实现隐藏的目的。为了实现这种目的,我们需要在另一个头文件中定义该嵌套类,而只在外围类中前向声明这个嵌套类即可。当然,在外围类外面定义这个嵌套类时,应该使用外围类进行限定。使用时,只需要在外围类的实现文件中包含这个头文件即可。
另外,嵌套类可以直接引用外围类的静态成员、类型名和枚举成员,即使这些是private的。
|
//PIMPL模式优点: (pointer to implementation)
//1. 实现信息隐藏
//2. 保持接口的稳定 --> 只要保证头文件不做修改,
// 对实现文件进行修改 --> 对库进行升级
//3. 如果是第三方公司在使用该库,可以做到平滑升级
// 它能够满足二进制兼容性
//pointer to implementation, 指向实现的指针
--------nested.h--------
#ifndef __NESTED_H__
#define __NESTED_H__
#include<iostream>
using namespace std;
class Line
{
private:
class LinePimpl; // 前向声明
LinePimpl* _LinePimpl;
public:
Line(int,int,int,int);
~Line();
void printLine();
};
#endif
--------main.cpp--------
#include"nested.h"
#include<iostream>
using namespace std;
int main()
{
Line l1(1,2,3,4);
l1.printLine();
return 0;
}
|
--------nested.cpp--------
// LinePimpl 实现
#include"nested.h"
#include<iostream>
using namespace std;
class Line::LinePimpl // 这里的Line::可以不要,类里面只是前向声明,不存在作用域范围
{
private:
class Point // 嵌套类
{
int _x; // 最开头,默认private
int _y;
public:
Point(int x=0,int y=0):_x(x),_y(y)
{
cout<<"Line::LinePimpl::Point::Point(int,int)"<<endl;
}
~Point()
{
cout<<"Line::LinePimpl::Point::~Point()"<<endl;
}
void printPoint();
};
Point _p1;
Point _p2;
public:
LinePimpl(int ix=0,int iy=0,int jx=0,int jy=0):_p1(ix,iy),_p2(jx,jy)
{
cout<<"Line::LinePimpl::LinePimpl(int,int,int,int)"<<endl;
}
~LinePimpl()
{
cout<<"Line::LinePimpl::~LinePimpl()"<<endl;
}
void printLine();
};
void Line::LinePimpl::Point::printPoint()
{
cout<<"Line::LinePimpl::Point::printPoint()"<<endl;
cout<<"("<<_x<<","<<_y<<")"<<endl;
}
void Line::LinePimpl::printLine()
{
cout<<"Line::LinePimpl::printLine()"<<endl;
_p1.printPoint();
cout<<"->"<<endl;
_p2.printPoint();
}
//外围类Line实现
Line::Line(int x1=0,int y1=0,int x2=0,int y2=0):_LinePimpl(new LinePimpl(x1,y1,x2,y2))
{
cout<<"Line::Line(int,int,int,int)"<<endl;
}
Line::~Line()
{
cout<<"Line::~Line()"<<endl;
delete _LinePimpl;
}
void Line::printLine()
{
cout<<"Line::printLine()"<<endl;
_LinePimpl->printLine();
}
|
嵌套类,PIMPL的更多相关文章
- 类声明、类作用域、前向声明、this指针、嵌套类、PIMPL 技法 等
一.类声明 //类是一种用户自定义类型,声明形式: class 类名称 { public: 公有成员(外部接口) private: 私有 ...
- spring 笔记1: mvn 中Controller方法的参数不能是嵌套类(内部类)。
最近做spring开发,个人认为,Controller和客户端js通讯时传递的参数类 只使用某几个方法,为了减少对其他功能的影响,想把参数类定义为Controller类的 嵌套类(内部类).但是实践发 ...
- JAVA 嵌套类和内部类
一.什么是嵌套类及内部类? 可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型: 静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套类, ...
- 学习django之构建Web是Meta嵌套类的几处使用
Django中meta嵌套类的使用 1.模型中使用嵌套类 在定义抽象模型时如: class Meta : abstract=true 用来指明你创建的模型是一个抽象基础类的模型继承. 2.在一个对象对 ...
- java嵌套类
java有四种嵌套类: 静态内部类,成员内部类,局部内部类,匿名内部类 1)静态内部类: (1)类的申明加上staitc关键字.一般用public修饰 (2)只能访问外部类的静态变量和静态方法.不能访 ...
- scala 学习笔记(04) OOP(上)主从构造器/私有属性/伴生对象(单例静态类)/apply方法/嵌套类
一.主从构造器 java中构造函数没有主.从之分,只有构造器重载,但在scala中,每个类都有一个主构造器,在定义class时,如果啥也没写,默认有一个xxx()的主构造器 class Person ...
- c++嵌套类-内存分配
首先看下列代码:int main(){ double *p; printf("sizeof(int):%d\nsizeof(double):%d\nsizeof(ptr):%d\ ...
- Java内部类、静态嵌套类、局部内部类、匿名内部类
Nested classes are further divided into two types: static nested classes: If the nested class is sta ...
- java 嵌套类 简记
嵌套类包括:1)静态嵌套类 (static 修饰符) 2)非静态嵌套类(又叫内部类) 其中内部类又可分为三种: 其一.在一个类(外部类)中直接定义的内部类: 其二.在一个方法(外部类的方法)中定义的 ...
随机推荐
- NGUI混合FingerGesture《卷二》分离触摸事件
背景 在使用NGUI按钮组件的时候,点击按钮同时触发FingerGesture的Touch事件, 通俗点讲,NGUI点击之后,点击事件被FingerGesture又执行了一遍. 解决思路 持有一个全局 ...
- Java Hashtable详细介绍和使用示例
①对Hashtable有个整体认识 和HashMap一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射.Hashtable 继承于Dictionary,实现了Ma ...
- 在安装好MySql后忘记root的密码,或者给root添加密码
一.编辑MySql的配置文件:my.ini(在MySql安装目录下). 打开配置文件,在文件最后一行添加:skip-grant-tables,然后保存退出. 意思为就是在启mysql时不启动grant ...
- maven-surefire-plugin
本文参考自:https://www.cnblogs.com/qyf404/p/5013694.html surefire是maven里执行测试用例(包括testNG,Junit,pojo)的插件,他能 ...
- SublimeText3 编辑器使用小结
1. 快捷键: Command + shift + D : 复制当前行 Command + shift + K : 删除当前行 Command + J : 合并一行 Command + Enter : ...
- shell编程学习笔记之sed编辑器
在shell编程中,大多数处理的都是文本文件.对文本文件进行处理除了使用交互式文本编辑器(vi[m],gedit......)也可以使用另外一类:流编辑器. 流编辑器:使用预定义的编辑规则来对文本进行 ...
- SQL系列 - SQL语句优化个人总结
关于SQL语句优化方法 有些是通用的(如避免Select *): 有些不同的数据库管理系统有所区别(如Where子句顺序): 然后必须根据实际环境进行调优,因为即使是相同的数据库和表,在数据量或其他环 ...
- KindEditor ctrl+v添加图片功能
原理: 监听粘贴事件(paste) 获取粘贴版数据,读取到图片数据流进行加载base64 传到后台服务端直接输出为图片文件保存后返回图片读取路径插入编辑器中 /** * 获取编辑器对象 */ wind ...
- heartbeat-gui
一.简介gui heartbeat的v2版本将v1中haresources配置文件使用GUI图形配置接口来配置高可用集群.更加便捷,直观. 二.准备条件和资源规划见上文http://www.cnblo ...
- Hive中的数据倾斜
Hive中的数据倾斜 hive 1. 什么是数据倾斜 mapreduce中,相同key的value都给一个reduce,如果个别key的数据过多,而其他key的较少,就会出现数据倾斜.通俗的说,就是我 ...