zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C++ 嵌套类使用(一)

C++ 嵌套 使用
2023-09-27 14:29:32 时间
   在一个类的内部定义另一个类,我们称之为嵌套类(nested class),或者嵌套类型。之所以引入这样一个嵌套类,往往是因为外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现。

 

   在一个类的内部定义另一个类,我们称之为嵌套类(nested class),或者嵌套类型。之所以引入这样一个嵌套类,往往是因为外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现。
 
 
   虽然嵌套类在外围类内部定义,但它是一个独立的类,基本上与外围类不相关。它的成员不属于外围类,同样,外围类的成员也不属于该嵌套类。嵌套类的出现只是告诉外围类有一个这样的类型成员供外围类使用。并且,外围类对嵌套类成员的访问没有任何特权,嵌套类对外围类成员的访问也同样如此,它们都遵循普通类所具有的标号访问控制。
 
 
 
   若不在嵌套类内部定义其成员,则其定义只能写到与外围类相同的作用域中,且要用外围类进行限定,不能把定义写在外围类中。例如,嵌套类的静态成员就是这样的一个例子。
 
 
   前面说过,之所以使用嵌套类的另一个原因是达到底层实现隐藏的目的。为了实现这种目的,我们需要在另一个头文件中定义该嵌套类,而只在外围类中前向声明这个嵌套类即可。当然,在外围类外面定义这个嵌套类时,应该使用外围类进行限定。使用时,只需要在外围类的实现文件中包含这个头文件即可。
 

   另外,嵌套类可以直接引用外围类的静态成员、类型名和枚举成员(假定这些成员是公有的)。类型名是一个typedef名字、枚举类型名、或是一个类名。


实例如下:
 

#ifndef NESTCLASS_H_ 
#define NESTCLASS_H_ 

class A
{
public:
     A();
     ~A();
 
     void operate();
private:
     class B;
     B* m_b;
};
 
#endif 

 
#include "nestclass.h" 
#include  
using namespace std;
 
class A::B
{
public:
     B(){}
     ~B(){}
 
     void operate()
     {
         cout "B operate!" endl;
     }
};
 
A::A()
{
 
}
 
A::~A()
{
 
}
 
void A::operate()
{
    m_b = new B;
    cout "A operate!" endl;
    m_b- operate();
}

#include "nestclass.h" 

void main()
{
     A a;
     a.operate();
}
 
        在嵌套类的定义被看到之前我们只能声明嵌套类的指针和引用,如上面在A中定义为B m_b而不是B* m_b将会引发一个编译错误。

       关于C++嵌套类的详细用法请参考《C++ Primer 第三版》P551。

 

二、局部类

 

     类也可以定义在函数体内 这样的类被称为局部类(local class), 局部类只在定义它的局部域内可见,与嵌套类不同的是,在定义该类的局部域外没有语法能够引用局部类的成员, 因此,局部类的成员函数必须被定义在类定义中,在实际中,这就把局部类的成员函数的复杂性限制在几行代码中,否则,对读者来说,代码将变得很难理解。 


    因为没有语法能够在名字空间域内定义局部类的成员 ,所以也不允许局部类声明静态数据成员。

     在局部类中嵌套的类可以在其类定义之外被定义,但是,该定义必须出现在包含外围局部类定义的局部域内。在局部域定义中的嵌套类的名字必须由其外围类名限定修饰,在外围类中,该嵌套类的声明不能被省略。例如:

void foo( int val ) 

class Bar { 
public: 
  int barVal; 
  class nested; // 嵌套类的声明是必需的 
}; 
 
// 嵌套类定义 
class Bar::nested { 
  // ... 
}; 
}

 

     外围函数没有特权访问局部类的私有成员,当然,这可以通过使外围函数成为局部类的友元来实现。

    同嵌套类一样,局部类可以访问的外围域中的名字也是有限的,局部类只能访问在外围局部域中定义的类型名、静态变量以及枚举值,例如:

 

int a, val; 
 
void foo( int val ) 

static int si; 
enum Loc { a = 1024, b }; 
 
class Bar { 
public: 
  Loc locVal; // ok; 
  int barVal; 
  void fooBar( Loc l = a ) { // ok: Loc::a 
   barVal = val; // 错误: 局部对象 
   barVal = ::val; // OK: 全局对象 
   barVal = si; // ok: 静态局部对象 
   locVal = b; // ok: 枚举值 
  } 
}; 
// ... 
}

 

     在局部类体内,不包括成员函数定义中的 的名字解析过程是,在外围域中查找出现在局部类定义之前的声明,在局部类的成员函数体内的名字的解析过程是:在查找外围域之前 ,首先直找该类的完整域 。

 
     还是一样,如果先找到的声明使该名字的用法无效,则不考虑其他声明,即使在fooBar() 中使用 val 是错的,编译器也不会找到全局变量val ,除非用全局域解析操作符限定修饰 val,如 ::val 。


C++ 嵌套类使用(三) 如果嵌套类型和其外部类型之间的关系需要成员可访问性语义,需要使用C++嵌套类,嵌套类型不应针对其声明类型以外的类型执行任务,而C++局部类允许类、结构和接口被分成多个小块儿并存储在不同的源文件中,这样的实现很容易开发和维护。
C++ 嵌套类使用(二) C++嵌套类 1、   嵌套类的名字只在外围类可见。 2、   类的私有成员只有类的成员和友元可以访问,因此外围类不可以访问嵌套类的私有成员。嵌套类可以访问外围类的成员(通过对象、指针或者引用)。 3、   一个好的嵌套类设计:嵌套类应该设成私有。
38、C++ Primer 4th笔记,特殊工具与技术,嵌套类 1、在一个类内部再定义另外一个类,这样的类称为嵌套类(nested class),也称为嵌套类型(nested type)。嵌套类最常用于执行类。 嵌套类是独立的类,基本上与它们的外围类不相关,因此,外围类和嵌套类的对象是互相独立的。
C++ Primer Plus 第6版 读书笔记(2)第2章 开始学习 C++ C++是在 C 语言基础上开发的一种集面向对象编程、泛型编程和过程化编程于一体的编程语言,是C语言的超集。本书是根据2003年的ISO/ANSI C++标准编写的,通过大量短小精悍的程序详细而全面地阐述了 C++的基本概念和技术,并专辟一章介绍了C++11新增的功能。
C++ STL学习之【反向迭代器】 适配器模式是 STL 中的重要组成部分,在上一篇文章中我们学习了 容器适配器 的相关知识,即 stack 与 queue,除了 容器适配器 外,还有 迭代器适配器,借助 迭代器适配器,可以轻松将各种容器中的普通迭代器转变为反向迭代器,这正是适配器的核心思想
C++ STL学习之【容器适配器】 适配器(配接器)是 STL 中的六大组件之一,扮演着轴承、转换器的角色,使得 STL 中组件的使用更为灵活,比如 栈和队列 就是属于适配器而非容器,以及神秘的反向迭代器也属于适配器
C++ STL学习之【vector的模拟实现】 vector 是 STL 中的容器之一,其使用方法类似于数据结构中的 顺序表,得益于范型编程和 C++ 特性的加持,vector 更强大、更全能;在模拟实现 vector 时,还需要注意许多细枝末节,否则就很容易造成重复析构及越界访问