C++中嵌套类的使用

一个类可以定义在另一个类的内部,前者称为嵌套类(nested class)或嵌套类型(nested type)。嵌套类常用于定义作为实现部分的类。嵌套类可用于隐藏实现细节。

嵌套类是一个独立的类,与外层类基本没什么关系。特别是,外层类的对象和嵌套类的对象是相互独立的。在嵌套类的对象中不包含任何外层类定义的成员;类似的,在外层类的对象中也不包含任何嵌套类定义的成员。

嵌套类的名字在外层类作用域中是可见的,在外层类作用域之外不可见。和其它嵌套的名字一样,嵌套类的名字不会和别的作用域中的同一个名字冲突。

嵌套类中成员的种类与非嵌套类是一样的。和其它类类似,嵌套类也使用访问限定符来控制外界对其成员的访问权限。外层类对嵌套类的成员没有特殊的访问权限,同样,嵌套类对外层类的成员也没有特殊的访问权限。

嵌套类在其外层类中定义了一个类型成员。和其它成员类似,该类型的访问权限由外层类决定。位于外层类public部分的嵌套类实际上定义了一种可以随处访问的类型;位于外层类protected部分的嵌套类定义的类型只能被外层类及其友元和派生类访问;位于外层类private部分的嵌套类定义的类型只能被外层类的成员和友元访问。

嵌套类必须声明在类的内部,但是可以定义在类的内部或者外部。当我们在外层类之外定义一个嵌套类时,必须以外层类的名字限定嵌套类的名字。在嵌套类在其外层类之外完成真正的定义之前,它都是一个不完全类型。

嵌套类和外层类是相互独立的:尽管嵌套类定义在其外层类的作用域中,但是外层类的对象和嵌套类的对象没有任何关系。嵌套类的对象只包含嵌套类定义的成员;同样,外层类的对象只包含外层类定义的成员,在外层类对象中不会有任何嵌套类的成员。

在C++11之前,嵌套类仅仅可以使用外层类的类型名、静态成员和枚举类型。但在C++11中,遵循非静态成员的通用使用规则,嵌套类可以使用外层类的任何成员。

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "nested_class.hpp"
#include <iostream>
#include <vector>
#include <typeinfo>

namespace nested_class_ {
//////////////////////////////////////////////////////////
// reference: http://en.cppreference.com/w/cpp/language/nested_types
int x, y; // globals
class enclose { // enclosing class
	int x; // note: private members
	static int s;
public:
	struct inner { // nested class
		void f(int i) {
			//x = i; // Error: can't write to non-static enclose::x without instance
			//int a = sizeof(x); // Error until C++11,
					   // OK in C++11: operand of sizeof is unevaluated,
					   // this use of the non-static enclose::x is allowed.
			s = i;   // OK: can assign to the static enclose::s
			::nested_class_::x = i; // OK: can assign to global x
			y = i;   // OK: can assign to global y
		}
		void g(enclose* p, int i) {
			p->x = i; // OK: assign to enclose::x
		}
	};
};

class enclose_ {
	struct nested { // private member
		void g() {}
	};
public:
	static nested f() { return nested{}; }
};

int test_nested_class_1()
{
	//enclose_::nested n1 = enclose_::f(); // error: 'nested' is private

	enclose_::f().g(); // OK: does not name 'nested'
	auto n2 = enclose_::f(); // OK: does not name 'nested'
	n2.g();

	return 0;
}

////////////////////////////////////////////////////////
// reference: http://www.sanfoundry.com/c-tutorials-nested-structure-access/
/* structure A declared */
typedef struct A {
	int a;
	float b;
} New_a;

/* structure B declared */
typedef struct B {
	int c;
	float d;
	struct A e;    /* member 'e' is itself a structure */
} New_b;

int test_nested_class_2()
{
	/* Let's declare variables of New_a and New_b */
	New_a bread;
	New_b butter;        /* 'butter' is a nested structure */

	/* Let's access bread using dot operator */
	bread.a = 10;        /* assigned member a value 10 */
	bread.b = 25.50;

	/* Let's access butter using dot operator */
	butter.c = 10;
	butter.d = 50.00;

	/* Let's access member 'e' which is a nested structure */
	butter.e.a = 20;
	butter.e.b = 20.00;

	/* Display values of members of 'butter.e' structure */
	printf("butter.e.a is %4d\n", butter.e.a);
	printf("butter.e.b is %.2f\n", butter.e.b);

	return 0;
}

////////////////////////////////////////////////////
// reference: http://www.geeksforgeeks.org/nested-classes-in-c/
/* start of Enclosing class declaration */
class Enclosing {

	int x;

	/* start of Nested class declaration */
	class Nested {
		int y;
		void NestedFun(Enclosing *e) {
			std::cout << e->x;  // works fine: nested class can access
			// private members of Enclosing class
		}
	}; // declaration Nested class ends here
}; // declaration Enclosing class ends here

int test_nested_class_3()
{
	return 0;
}

////////////////////////////////////////////////////////////
// reference: http://www.oopweb.com/CPP/Documents/CPPAnnotations/Volume/cplusplus16.html
class Clonable {
public:
	class Base {
	public:
		virtual ~Base() {}
		virtual Base *clone() const = 0;
	};

private:
	Base *d_bp;

public:
	Clonable() : d_bp(0) {}
	~Clonable() { delete d_bp; }
	Clonable(Clonable const &other) { copy(other); }

	Clonable &operator=(Clonable const &other)
	{
		if (this != &other) {
			delete d_bp;
			copy(other);
		}
		return *this;
	}

	// New for virtual constructions:
	Clonable(Base const &bp)
	{
		d_bp = bp.clone();      // allows initialization from
	}                           // Base and derived objects

	Base &get() const
	{
		return *d_bp;
	}

private:
	void copy(Clonable const &other)
	{
		if ((d_bp = other.d_bp))
			d_bp = d_bp->clone();
	}
};

class Derived1 : public Clonable::Base
{
public:
	~Derived1()
	{
		std::cout << "~Derived1() called\n";
	}
	virtual Clonable::Base *clone() const
	{
		return new Derived1(*this);
	}
};

int test_nested_class_4()
{
	std::vector<Clonable> bv;

	bv.push_back(Derived1());
	std::cout << "==\n";

	std::cout << typeid(bv[0].get()).name() << std::endl;
	std::cout << "==\n";

	std::vector<Clonable> v2(bv);
	std::cout << typeid(v2[0].get()).name() << std::endl;
	std::cout << "==\n";

	return 0;
}

/////////////////////////////////////////////////////////
// reference: http://www.sanfoundry.com/cpp-program-illustrate-nested-classes/
class Stack {
	class Node {
	public:
		int data;
		Node* next;
		Node(int data, Node* next);
		~Node();
	}*head;
public:
	Stack();
	Stack(const Stack& s);
	void operator=(const Stack& s);
	~Stack();
	void push(int data);
	int peek() const;
	int pop();
};

Stack::Node::Node(int data, Node* next)
{
	this->data = data;
	this->next = next;
}

Stack::Node::~Node() { }

Stack::Stack() { head = NULL; }

Stack::Stack(const Stack& s)
{
	head = s.head;
}

void Stack::operator=(const Stack& s)
{
	head = s.head;
}

void Stack::push(int data)
{
	head = new Node(data, head);
}

int Stack::peek() const {
	if (head == 0) {
		std::cerr << "Stack empty!" << std::endl;
		return -1;
	}
	else
		return head->data;
}

int Stack::pop()
{
	if (head == NULL) return -1;
	int result = head->data;
	Node* oldNode = head;
	head = head->next;
	delete oldNode;
	return result;
}

Stack::~Stack()
{
	if (head != NULL) {
		while (head->next != NULL) {
			Node* temp = head;
			head = head->next;
			delete temp;
		}
	}
}

int test_nested_class_5()
{
	Stack Integers;
	int value, num;

	std::cout << "Enter the number of elements ";
	std::cin >> num;
	while (num > 0) {
		std::cin >> value;
		Integers.push(value);
		num--;
	}
	while ((value = Integers.pop()) != -1)
		std::cout << "Top element of stack  " << value << std::endl;

	return 0;
}

//////////////////////////////////////////////////////////////
// reference: https://msdn.microsoft.com/en-us/library/71dw8xzh.aspx
class X
{

	template <class T>
	struct Y {
		T m_t;
		Y(T t) : m_t(t) { }
	};

	Y<int> yInt;
	Y<char> yChar;

public:
	X(int i, char c) : yInt(i), yChar(c) { }
	void print()
	{
		std::cout << yInt.m_t << " " << yChar.m_t << std::endl;
	}
};

int test_nested_class_6()
{
	X x(1, 'a');
	x.print();

	return 0;
}

///////////////////////////////////////////
// reference: https://msdn.microsoft.com/en-us/library/71dw8xzh.aspx
template <class T>
class X_
{
	template <class U>
	class Y {
		U* u;
	public:
		Y();
		U& Value();
		void print();
		~Y();
	};

	Y<int> y;
public:
	X_(T t) { y.Value() = t; }
	void print() { y.print(); }
};

template <class T>
template <class U>
X_<T>::Y<U>::Y()
{
	std::cout << "X_<T>::Y<U>::Y()" << std::endl;
	u = new U();
}

template <class T>
template <class U>
U& X_<T>::Y<U>::Value()
{
	return *u;
}

template <class T>
template <class U>
void X_<T>::Y<U>::print()
{
	std::cout << this->Value() << std::endl;
}

template <class T>
template <class U>
X_<T>::Y<U>::~Y()
{
	std::cout << "X_<T>::Y<U>::~Y()" << std::endl;
	delete u;
}

int test_nested_class_7()
{
	X_<int>* xi = new X_<int>(10);
	X_<char>* xc = new X_<char>('c');
	xi->print();
	xc->print();
	delete xi;
	delete xc;

	return 0;
}

} // namespace nested_class_

GitHub: https://github.com/fengbingchun/Messy_Test 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值