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;}

类作用域:
1、作用域可分为类作用域、类名的作用域以及对象的作用域几部分内容。
2、在类中定义的成员变量和成员函数的作用域是整个类,这些名称只有在类中(包含类的定义部分和类外函数实现部分)是可见的,在类外是不可见的,因此,可以在不同类中使用相同的成员名。另外,类作用域意味着不能从外部直接访问类的任何成员,即使该成员的访问权限是public,也要通过对象名来调用,对于static成员,要指定类名来调用。
3、如果发生“屏蔽”现象,类成员的可见域将小于作用域,但此时可借助this指针或“类名::”形式指明所访问的是类成员,这有些类似于使用“::”访问全局变量。
#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;

}

类定义的作用域与可见域:

使用类名创建对象时,首要的前提是类名可见,类名是否可见取决于类定义的可见域,该可见域同样包含在其作用域中,类本身可被定义在3种作用域内,这也是类定义的作用域:
(1)全局作用域
在函数和其他类定义的外部定义的类称为全局类,全局类具有全局作用域。

(2)类作用域 ( 类中类、嵌套类 )
一个类可以定义在另一类的定义中,这是所谓嵌套类,举例来说,如果类A定义在类B中,如果A的访问权限是public,则A的作用域可认为和B的作用域相同,不同之处在于必须使用B::A的形式访问A的类名。当然,如果A的访问权限是private,则只能在类内使用类名创建该类的对象,无法在外部创建A类的对象。
(3)块作用域
类的定义在代码块中,这是所谓局部类,该类完全被块包含,其作用域仅仅限于定义所在块,不能在块外使用类名声明该类的对象。

(4)类名也存在覆盖
和普通变量的覆盖原则一样,类名也存在“屏蔽”和“覆盖”,不过,依旧可使用作用域声明符“::”指定具体使用的类名,如“::类名”访问的是全局类,使用“外部类::嵌套类”访问嵌套类。
在一个类的内部定义另一个类,我们称之为嵌套类(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的更多相关文章

  1. 类声明、类作用域、前向声明、this指针、嵌套类、PIMPL 技法 等

    一.类声明 //类是一种用户自定义类型,声明形式: class 类名称 {    public:              公有成员(外部接口)    private:              私有 ...

  2. spring 笔记1: mvn 中Controller方法的参数不能是嵌套类(内部类)。

    最近做spring开发,个人认为,Controller和客户端js通讯时传递的参数类 只使用某几个方法,为了减少对其他功能的影响,想把参数类定义为Controller类的 嵌套类(内部类).但是实践发 ...

  3. JAVA 嵌套类和内部类

    一.什么是嵌套类及内部类?  可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:  静态嵌套类和非静态嵌套类.静态嵌套类使用很少,最重要的是非静态嵌套类, ...

  4. 学习django之构建Web是Meta嵌套类的几处使用

    Django中meta嵌套类的使用 1.模型中使用嵌套类 在定义抽象模型时如: class Meta : abstract=true 用来指明你创建的模型是一个抽象基础类的模型继承. 2.在一个对象对 ...

  5. java嵌套类

    java有四种嵌套类: 静态内部类,成员内部类,局部内部类,匿名内部类 1)静态内部类: (1)类的申明加上staitc关键字.一般用public修饰 (2)只能访问外部类的静态变量和静态方法.不能访 ...

  6. scala 学习笔记(04) OOP(上)主从构造器/私有属性/伴生对象(单例静态类)/apply方法/嵌套类

    一.主从构造器 java中构造函数没有主.从之分,只有构造器重载,但在scala中,每个类都有一个主构造器,在定义class时,如果啥也没写,默认有一个xxx()的主构造器 class Person ...

  7. c++嵌套类-内存分配

    首先看下列代码:int main(){    double *p;    printf("sizeof(int):%d\nsizeof(double):%d\nsizeof(ptr):%d\ ...

  8. Java内部类、静态嵌套类、局部内部类、匿名内部类

    Nested classes are further divided into two types: static nested classes: If the nested class is sta ...

  9. java 嵌套类 简记

    嵌套类包括:1)静态嵌套类  (static 修饰符) 2)非静态嵌套类(又叫内部类) 其中内部类又可分为三种: 其一.在一个类(外部类)中直接定义的内部类: 其二.在一个方法(外部类的方法)中定义的 ...

随机推荐

  1. qq第三方登录网站接口

    网站如何实现QQ登录功能 | 浏览:11029 | 更新:2013-12-05 10:09 1 2 3 4 5 6 7 分步阅读 一键约师傅 百度师傅为你的电脑系统,选一个靠谱师傅! 如果想让网站实现 ...

  2. Django学习笔记之Django QuerySet的方法

    一般情况下,我们在写Django项目需要操作QuerySet时一些常用的方法已经满足我们日常大多数需求,比如get.filter.exclude.delete神马的感觉就已经无所不能了,但随着项目但业 ...

  3. CF1155D Beautiful Array(动态规划)

    做法 \(f_{i,0}\)表示以\(i\)结尾未操作时的最大值 \(f_{i,1}\)表示以\(i\)结尾正在操作时的最大值 \(f_{i,2}\)表示以\(i\)结尾已结束操作时的最大值 Code ...

  4. RESTful风格与RESTful Api

    REST(representational state transfer)(表述性状态转移),词汇解析: 1.representational 表述性:指资源以用各种形式来表述,包括 XML.JSON ...

  5. vmware基于主机模式实现上网(win10)

    首先查看本机win10的网络情况: 网卡VMnet1就是主机模式的网卡,确认本机win10共享了网络给vmnet1这张网卡,如果没有共享,那么进行设置: 进行上述设置,然后在vmnet1网卡上设置ip ...

  6. 20145307第五次JAVA学习实验报告

    20145307<Java程序设计>第五次实验报告 北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验日期:2016.05.06 实验名 ...

  7. hdu 2896:病毒侵袭

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

  8. Oh My Zsh 插件篇 - 实用工具

    Oh My Zsh 除了为我们提供快捷的命令行操作之外,还提供了强大丰富的插件机制,每个社区贡献者都可以贡献自己的插件,让整个生态体系更加丰富完善.今天给大家介绍了一下它的实用工具类插件. 前面我们分 ...

  9. 混合开发的大趋势之一React Native之简单的登录界面

    转载请注明出处:王亟亟的大牛之路 这些天都在学习RN这部分吧,然后写了个简单的登陆业务,从"实战"中讲解吧 还是继续安利:https://github.com/ddwhan0123 ...

  10. 第九篇:Spark SQL 源码分析之 In-Memory Columnar Storage源码分析之 cache table

    /** Spark SQL源码分析系列文章*/ Spark SQL 可以将数据缓存到内存中,我们可以见到的通过调用cache table tableName即可将一张表缓存到内存中,来极大的提高查询效 ...