特殊工具与技术

--嵌套类

能够在还有一个类内部(与后面所讲述的局部类不同,嵌套类是在类内部)定义一个类,这种类是嵌套类,也称为嵌套类型。嵌套类最经常使用于定义运行类.

嵌套类是独立的类,基本上与它们的外围类不相关,因此,外围类和嵌套类的对象是互相独立的。嵌套类型的对象不具备外围类所定义的成员,相同,外围类的成员也不具备嵌套类所定义的成员。

嵌套类的名字在其外围类的作用域中可见,但在其它类作用域或定义外围类的作用域中不可见。嵌套类的名字将不会与还有一作用域中声明的名字冲突

嵌套类能够具有与非嵌套类相同种类的成员。像不论什么其它类一样,嵌套类使用訪问标号控制对自己成员的訪问。成员能够声明为 public、private 或 protected。外围类对嵌套类的成员没有特殊訪问权,并且嵌套类对其外围类的成员也没有特殊訪问权。

嵌套类定义了其外围类中的一个类型成员。像不论什么其它成员一样,外围类决定对这个类型的訪问。

嵌套类的实现

[实例]

将 QueueItem 类设为 Queue 类的 private 成员,那样,Queue 类(及其友元)能够使用 QueueItem,但 QueueItem 类类型对普通用户代码不可见。一旦 QueueItem 类本身为 private,我们就能够使其成员为 public 成员--仅仅有 Queue 或 Queue 的友元能够訪问 QueueItem 类型,所以不必防止一般程序訪问 QueueItem 成员。通过用保留字 struct 定义 QueueItem 使成员为 public 成员。

新的设计例如以下:

template <typename Type>
class Queue
{
public:
//... private:
struct QueueItem
{
QueueItem(const Type &);
Type item;
QueueItem *next;
}; QueueItem *head;
QueueItem *tail;
};

1.嵌套在类模板内部的类是模板

由于Queue是模板,因此它的成员也是模板,并且QueueItem的模板形參与其外围类Queue的模板形參相同.

Queue 类的每次实例化用相应于 Type 的适当模板实參产生自己的QueueItem 类。QueueItem 类模板的实例化与外围 Queue 类模板的实例化之间的映射是一对一的。

2.定义嵌套类的成员

在其类外部定义的嵌套类成员,必须定义在定义外围类的同一作用域中。在其类外部定义的嵌套类的成员,不能定义在外围类内部,嵌套类的成员不是外围类的成员。

QueueItem 类的构造函数不是 Queue 类的成员,因此,不能将它定义在Queue 类定义体中的不论什么地方.

template <class Type>
Queue<Type>::QueueItem::QueueItem(const Type &t):
item(t),next(0) {}

由于Queue和QueueItem是模板,因此该构造函数也为模板.

3.在外围类外部定义嵌套类

嵌套类通常支持外围类的实现细节。我们可能希望防止外围类的用户看见嵌套类的实现代码。

比如,我们可能希望将 QueueItem 类的定义放在它自己的文件里,我们能够在 Queue 类及其成员的实现文件里包括这个文件。正如能够在类定义体外部定义嵌套类的成员一样,我们也能够在外围类定义体的外部定义整个嵌套类:

template <typename Type>
class Queue
{
public:
//... private:
struct QueueItem; QueueItem *head;
QueueItem *tail;
}; template <class Type>
struct Queue<Type>::QueueItem
{
QueueItem(const Type &t):item(t),next(0) {} Type item;
QueueItem *next;
};

注意,我们必须在Queue类体内部声明QueueItem类.

[小心]

在看到在类定义体外部定义的嵌套类的实际定义之前,该类是不全然类型,应用全部使用不全然类型的常规限制。

4.嵌套类静态成员定义

假设QueueItem类声明了一个静态成员,它的定义也须要放在外层作用域中,假定QueueItem有一个静态成员:

template <class Type>
int Queue<Type>::QueueItem::static_mem = 1024;

5.使用外围类的成员

外围作用域的对象与其嵌套类型的对象之间没有联系

template <typename Type>
void Queue<Type>::pop()
{
QueueItem *q = head;
head = head -> next;
delete q;
}

Queue 类型的对象没有名为 item 或 next 成员。Queue 类的函数成员能够使用 head 和 tail 成员(它们是指向 QueueItem 对象的指针)来获取那些QueueItem 成员。

6.使用静态成员或其它类型的成员

嵌套类能够直接引用外围类的静态成员,类型名和枚举成员[同后面所讲的局部类].然而,引用外围类作用域之外的类型名或静态成员,须要作用域确定操作符.

7.嵌套模板的实例化

实例化外围类模板的时候,不会自己主动实例化类模板的嵌套类。像不论什么成员函数一样,仅仅有当在须要完整类类型的情况下使用嵌套类本身的时候,才会实例化嵌套类。比如,像

Queue<int> qi; 

这种定义,用 int 类型实例化了 Queue 模板,但没有实例化QueueItem<int> 类型。成员 head 和 tail 是指向 QueueItem<int> 指针,这里不须要实例化 QueueItem<int> 来定义那个类的指针。

仅仅有在使用 QueueItem<int> 的时候--仅仅有当 Queue<int> 类的成员函数中对 head 和 tail 解引用的时候,才实例化 QueueItem<int> 类。

嵌套类作用域中的名字查找

当处理类成员声明的时候,所用的名字必须在使用之前出现;当处理定义的时候,整个嵌套类和外围类均在作用域中.

class Outer
{
public:
struct Inner
{
void process(const Outer &); //OK
Inner2 val; //Error
};
struct Inner2
{
public:
Inner2(int i = 0):val(i) {} void process(const Outer &out) //OK
{
out.handle();
} private:
int val;
}; void handle() const;
};

[说明]

编译器首先处理 Outer 类成员的声明 Outer::Inner 和 Outer::Inner2。将名字 Outer 作为 Inner::process 形參的使用被绑定到外围类,在看到process 的声明时,那个类仍是不完整的,但形參是一个引用,所以这个使用是正确的。

数据成员 Inner::val 的声明是错误的,还没有看到 Inner2 类型。

Inner2 中的声明看来没有问题--它们大多仅仅使用内置类型 int。唯一的例外是成员函数 process,它的形參确定为不全然类型 Outer。由于其形參是一个引用,所以 Outer 为不全然类型是无关紧要的。

直到看到了外围类中的其余声明之后,编译器才处理构造函数和 process 成员的定义。对 Outer 类声明的完毕将函数 handle 的声明放在作用域中。

当编译器查找 Inner2 类中的定义所用的名字时,Inner2 类和 Outer 类中的全部名字都在作用域中。val 的使用(出如今 val 的声明之前)是正确的:将该引用绑定到 Inner2 类中的数据成员[不大理解这一段是什么意思%>_<%]。相同,Inner2::process 成员函数体中对 Outer 类的 handle 的使用也正确,当编译 Inner2 类的成员的时候,整个 Outer 类在作用域中。

使用作用域操作符控制名字查找

能够使用作用域操作符訪问handle的全局版本号:

        void process(const Outer &out)
{
::hadle(out);
}

C++ Primer 学习笔记_104_特殊工具与技术 --嵌套类的更多相关文章

  1. C++ Primer学习笔记(三) C++中函数是一种类型!!!

    C++中函数是一种类型!C++中函数是一种类型!C++中函数是一种类型! 函数名就是变量!函数名就是变量!函数名就是变量! (---20160618最新消息,函数名不是变量名...囧) (---201 ...

  2. C++ Primer学习笔记(二)

    题外话:一工作起来就没有大段的时间学习了,如何充分利用碎片时间是个好问题. 接  C++ Primer学习笔记(一)   27.与 vector 类型相比,数组的显著缺陷在于:数组的长度是固定的,无法 ...

  3. Android:日常学习笔记(9)———探究持久化技术

    Android:日常学习笔记(9)———探究持久化技术 引入持久化技术 什么是持久化技术 持久化技术就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失 ...

  4. C#可扩展编程之MEF学习笔记(三):导出类的方法和属性

    前面说完了导入和导出的几种方法,如果大家细心的话会注意到前面我们导出的都是类,那么方法和属性能不能导出呢???答案是肯定的,下面就来说下MEF是如何导出方法和属性的. 还是前面的代码,第二篇中已经提供 ...

  5. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78516 ...

  6. Duilib学习笔记《06》— 窗体基类WindowImpBase

    在前面的例子中我们发现,窗口都是继承CWindowWnd.INotifyUI,然后重载相关函数去实现.显然,我们发现窗口的创建流程实际上都是差不多的,主要只是在OnCreate加载的配置文件不同等等… ...

  7. cocos2d-x实战 C++卷 学习笔记--第4章 字符串 __String类

    前言: <cocos2d-x实战C++卷>学习笔记.(cocos2d-x 是3.0版本) 介绍 cocos2d-x 通用的字符串类  __String . 使用cocos2d::__Str ...

  8. Python学习笔记(十五):类基础

    以Mark Lutz著的<Python学习手册>为教程,每天花1个小时左右时间学习,争取两周完成. --- 写在前面的话 2013-7-24 23:59 学习笔记 1,Python中的大多 ...

  9. mybatis学习笔记(二)-- 使用mybatisUtil工具类体验基于xml和注解实现

    项目结构  基础入门可参考:mybatis学习笔记(一)-- 简单入门(附测试Demo详细过程) 开始体验 1.新建项目,新建类MybatisUtil.java,路径:src/util/Mybatis ...

随机推荐

  1. 11、DMA操作说明

    先理解cache的作用CPU在访问内存时,首先判断所要访问的内容是否在Cache中,如果在,就称为“命中(hit)”,此时CPU直接从Cache中调用该内容:否则,就 称为“ 不命中”,CPU只好去内 ...

  2. 3D 应用程序性能

    原文:3D 应用程序性能 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/details/74595999 3 ...

  3. Eclipse下配置Ant脚本 自己主动打包带签名的Android apk

    尽管eclipse非常少用了,可是在古老的项目上还是会用到.一个麻烦事是打带签名包的时候.非常不方便.下边纪录下配置ant,自己主动打包带签名apk的过程,作为备忘.(PC环境为MAC) 1,第一步得 ...

  4. Web系统自动化部署脚本

    Web开发的项目,除了在本地直接运行外,还可能经常需要在服务器上部署. 写了个自动化部署的脚本,仅供参考. 不少地方需要配置路径,个人建议使用绝对路径,不用依赖执行脚本时所在的路径. #!/bin/s ...

  5. [Elm] Functions in Elm

    Functions are an important building block in Elm. In this lesson we will review stateless functions, ...

  6. XML输出到浏览器报错

    在使用Firefox浏览器测试我编写的xml文件时,遇到如下错误:我的xml源代码如下: <?xml version="1.0" encoding="UTF-8&q ...

  7. 【b802】火柴棒等式

    Time Limit: 1 second Memory Limit: 50 MB [问题描述] 给你n根火柴棍,你可以拼出多少个形如"A+B=C"的等式?等式中的A.B.C是用火柴 ...

  8. 【codeforces 742C】Arpa's loud Owf and Mehrdad's evil plan

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  9. RSA Android加密的数据服务器上无法解密?

    一.android加密的数据服务器上无法解密? "算法/模式/填充" android的rsa加密方式是--------RSA/ECB/NoPadding或者RSA/None/NoP ...

  10. 【CF706C】Hard problem

    Description Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve h ...