C++ Primer Plus 书之--C++ 嵌套类(内部类), 嵌套类访问权限

嵌套类

在C++中, 可以将类声明放在另一个类中. 在另一个类中声明的类被称为嵌套类(nested class), 它通过提供新的类型类作用域来避免名称混乱. 包含类的成原函数可以创建和使用被嵌套类的对象; 而仅当声明位于共有部分, 才能在包含类的外面使用嵌套类, 而且必须使用作用域解析运算符.

对类进行嵌套和包含并不同, 包含意味着将类对象作为另一个类的成员, 而对类进行嵌套不创建类成员, 而是定义了一种类型, 该类型仅在包含嵌套类声明的类中有效.

们先看一个之前的一个例子, 自定义实现的简化版的队列:

class Queue
{
private:
	// 这里Node是一个嵌套的结构体定义
	// Item是一个别名, 详见之前的笔记
	struct Node {Item item; struct Node * next;}
	...
};

由于结构是一种其成员在默认情况下为共有的类, 所以Node实际上是一个嵌套类.

在之前的笔记中创建Node对象的方法是这么写的:

bool Queue::enqueue(const Item & item)
{
	if(isfull())
		return false;
	Node * add = new Node;
	add->item = item;
	add->next = NULL:
	...
}

现在我们将Node由struct改为嵌套类:

class Queue
{
	// 嵌套类
	class Node
	{
	public:
		Item item;
		Node * next;
		// 构造函数, 将item赋值为i, next指针设置为0, 也就是空值指针
		Node(const Item & i): item(i), next(0) {}
	};
	...
};

然后, 重新使用构造函数编写enqueue():

bool Queue::enqueue(const Item & item)
{
	if(isfull())
		return false;
	Node * add = new Node(item);
	...
}

这个例子中是在类声明中定义了构造函数, 假设想在方法文件中定义构造函数, 则定义必须指出Node类是在Queue类中定义的, 我们可以通过两次作用域解析运算符来完成:

Queue::Node::Node(const Item & i): item(i), next(0) {}

 

嵌套类和访问权限:

首先.嵌套类的声明位置决定了嵌套类的作用域, 即它决定了程序的那些部分可以创建这种类的对象.

其次.嵌套类的共有部分, 保护部分和私有部分控制了对类成员的访问.

1.作用域

如果嵌套类是在另一个类的私有部分声明的, 则只有后者知道它. 前面的例子中Node就是这种情况, 虽然Node没有明确写是private的, 但是默认就是private的. 因此Queue成员可以使用Node对象和指向Node对象的指针, 但是程序的其他部分不知道存在Node类, 对于从Queue派生而来的类, Node也是不可见的, 因为派生类不能直接访问基类的私有部分.

如果嵌套类是在另一个类的保护部分声明的, 则它对于后者可见, 但是对于外部世界是不可见的. 但是这种情况中, 派生类是知道嵌套类的, 并可以直接创建这种类型的对象.

如果嵌套类是在另一个类的共有部分声明的, 则允许后者, 后者的派生类以及外部世界使用它, 因为它是共有的. 然而, 由于嵌套类的作用域为包含它的类, 因此在外部世界使用它时, 必须使用类限定符.

假设有如下的声明:

class Team
{
public:
	class Coach {...};
	...
};

如果要在Team外面创建Coach对象, 可以这么写:

Team::Coach forhire;

2.访问控制

对嵌套类的访问控制规则与常规类相同. 在Queue类声明中声明Node类并没有赋予Queue类的访问特权, 也没有赋予Node类任何对Queue类的访问特权. 因此Queue类对象只能显示的访问Node对象的共有成员.

 

类声明的位置决定了类的作用域或可见性, 类可见后, 访问控制规则(共有, 保护, 私有, 友元)将决定程序对嵌套类成员的访问权限.

 

模板中的嵌套

模板类中同样可以使用嵌套类

// queuetp.h
#ifndef QUEUETP_H_
#define QUEUETP_H_

// 模板类
template <class Item>
class QueueTP
{
private:
	enum {Q_SIZE = 10};
	// 定义一个嵌套类
	class Node
	{
	public:
		Item item;
		Node * next;
		Node(const Item & i):item(i), next(0){}
	};
	Node * front;
	Node * rear;
	int items;
	const int qsize;
	QueueTP(const QueueTP & q): qsize(0) {}
	QueueTP & operator=(const QueueTP & q) {return *this;}

public:
	QueueTP(int qs = Q_SIZE);
	~QueueTP();
	bool isempty() const
	{
		return items == 0;
	}
	bool isfull() const
	{
		return items == qsize;
	}
	bool queuecount() const
	{
		return items;
	}
	bool enqueue(const Item & item);
	bool dequeue(Item & item);
};

template<class Item>
QueueTP<Item>::QueueTP(int qs):qsize(qs)
{
	// 置为空值指针
	front = rear = 0;
	items = 0;
}

template<class Item>
QueueTP<Item>::~QueueTP()
{
	Node * temp;
	while(front != 0)
	{
		temp = front;
		front = front->next;
		delete temp;
	}
}

template <class Item>
bool QueueTP<Item>::enqueue(const Item & item)
{
	if(isfull())
		return false;
	Node * add = new Node(item);
	items++;
	if(front == 0)
	{
		front = add;
	} else {
		rear->next = add;
	}
	rear = add;
	return true;	
}

template<class Item>
bool QueueTP<Item>::dequeue(Item & item)
{
	if(front == 0)
		return false;
	item = front->item;
	items--;
	Node * temp = front;
	front = front->next;
	delete temp;
	if(items == 0)
		rear = 0;
	return true;
}

#endif

第二个文件:

// 测试类
// nested.cpp
#include <iostream>
#include <string>
#include "queuetp.h"

int main()
{
	using std::string;
	using std::cin;
	using std::cout;
	using std::endl;
	
	QueueTP<string> cs(5);
	string temp;
	
	while(!cs.isfull())
	{
		cout << "Please enter your name. You will be served in the order of arrival. name:" << endl;
		getline(cin, temp);	
		cs.enqueue(temp);
	}
	cout << "The queue is full. Processing begins!" << endl;
	while(!cs.isempty())
	{
		cs.dequeue(temp);
		cout << "Now Processing " << temp << "..." << endl;
	}
	return 0;
}

程序运行结果为:

《C++ Primer Plus 书之--C++ 嵌套类(内部类), 嵌套类访问权限》

 

 

 

 

 

    原文作者:c1392851600
    原文地址: https://blog.csdn.net/c1392851600/article/details/85332435
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞