C++中嵌套类的使用
一個(gè)類(lèi)可以定義在另一個(gè)類(lèi)的內(nèi)部,前者稱為嵌套類(lèi)(nested class)或嵌套類(lèi)型(nested type)。嵌套類(lèi)常用于定義作為實(shí)現(xiàn)部分的類(lèi)。嵌套類(lèi)可用于隱藏實(shí)現(xiàn)細(xì)節(jié)。
嵌套類(lèi)是一個(gè)獨(dú)立的類(lèi),與外層類(lèi)基本沒(méi)什么關(guān)系。特別是,外層類(lèi)的對(duì)象和嵌套類(lèi)的對(duì)象是相互獨(dú)立的。在嵌套類(lèi)的對(duì)象中不包含任何外層類(lèi)定義的成員;類(lèi)似的,在外層類(lèi)的對(duì)象中也不包含任何嵌套類(lèi)定義的成員。
嵌套類(lèi)的名字在外層類(lèi)作用域中是可見(jiàn)的,在外層類(lèi)作用域之外不可見(jiàn)。和其它嵌套的名字一樣,嵌套類(lèi)的名字不會(huì)和別的作用域中的同一個(gè)名字沖突。
嵌套類(lèi)中成員的種類(lèi)與非嵌套類(lèi)是一樣的。和其它類(lèi)類(lèi)似,嵌套類(lèi)也使用訪問(wèn)限定符來(lái)控制外界對(duì)其成員的訪問(wèn)權(quán)限。外層類(lèi)對(duì)嵌套類(lèi)的成員沒(méi)有特殊的訪問(wèn)權(quán)限,同樣,嵌套類(lèi)對(duì)外層類(lèi)的成員也沒(méi)有特殊的訪問(wèn)權(quán)限。
嵌套類(lèi)在其外層類(lèi)中定義了一個(gè)類(lèi)型成員。和其它成員類(lèi)似,該類(lèi)型的訪問(wèn)權(quán)限由外層類(lèi)決定。位于外層類(lèi)public部分的嵌套類(lèi)實(shí)際上定義了一種可以隨處訪問(wèn)的類(lèi)型;位于外層類(lèi)protected部分的嵌套類(lèi)定義的類(lèi)型只能被外層類(lèi)及其友元和派生類(lèi)訪問(wèn);位于外層類(lèi)private部分的嵌套類(lèi)定義的類(lèi)型只能被外層類(lèi)的成員和友元訪問(wèn)。
嵌套類(lèi)必須聲明在類(lèi)的內(nèi)部,但是可以定義在類(lèi)的內(nèi)部或者外部。當(dāng)我們?cè)谕鈱宇?lèi)之外定義一個(gè)嵌套類(lèi)時(shí),必須以外層類(lèi)的名字限定嵌套類(lèi)的名字。在嵌套類(lèi)在其外層類(lèi)之外完成真正的定義之前,它都是一個(gè)不完全類(lèi)型。
嵌套類(lèi)和外層類(lèi)是相互獨(dú)立的:盡管嵌套類(lèi)定義在其外層類(lèi)的作用域中,但是外層類(lèi)的對(duì)象和嵌套類(lèi)的對(duì)象沒(méi)有任何關(guān)系。嵌套類(lèi)的對(duì)象只包含嵌套類(lèi)定義的成員;同樣,外層類(lèi)的對(duì)象只包含外層類(lèi)定義的成員,在外層類(lèi)對(duì)象中不會(huì)有任何嵌套類(lèi)的成員。
在C++11之前,嵌套類(lèi)僅僅可以使用外層類(lèi)的類(lèi)型名、靜態(tài)成員和枚舉類(lèi)型。但在C++11中,遵循非靜態(tài)成員的通用使用規(guī)則,嵌套類(lèi)可以使用外層類(lèi)的任何成員。
下面是從其他文章中copy的測(cè)試代碼,詳細(xì)內(nèi)容介紹可以參考對(duì)應(yīng)的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 classint x; // note: private membersstatic int s;
public:struct inner { // nested classvoid 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 xy = 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 membervoid g() {}};
public:static nested f() { return nested{}; }
};int test_nested_class_1()
{//enclose_::nested n1 = enclose_::f(); // error: 'nested' is privateenclose_::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 hereint 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 objectsBase &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;}elsereturn 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?
總結(jié)
以上是生活随笔為你收集整理的C++中嵌套类的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C++中局部类的使用
- 下一篇: C++11中enum class的使用