14.面向对象-封装-嵌套类
14.1 知识点
嵌套类是什么
- 嵌套类是指声明定义在一个类内部的类
- 就像俄罗斯套娃一样,在类当中还有类的声明和定义
嵌套类的声明和定义
嵌套类的声明:
- 直接在某一个类中(类语句块中)
- 按照类声明语法进行声明
嵌套类的定义:
- 在宿主类中直接定义或在其
.cpp
中进行定义 - 定义时需要使用
类名::类名::成员名
这种形式明确属于哪一个类
- 在宿主类中直接定义或在其
注意:
- 嵌套类和外部类本质上是彼此独立的,嵌套类并不像外部类的成员那样紧密
- 嵌套类和普通类使用上唯一的区别就是需要使用
类名::类名
这种形式表明它是嵌套在一个类之中的
#pragma once
class Outer
{
public:
int i = 10;
//private:
//如果嵌套类是私有的就不能在外部使用了
class Inner
{
private:
int i = 10;
public:
float f = 4.5f;
void test();
//允许无限嵌套
class OuterInnerInner
{
public:
class OuterInnerInner2
{
public:
class OuterInnerInner3
{
};
};
};
protected:
double d = 5.5;
};
//可以有多个嵌套类
class Inner2
{
};
//Outer类有个Inner类的成员
Inner inner;
};
#include "Outer.h"
// 我们在定义嵌套类中的成员时,需要明确它被谁包裹着
void Outer::Inner::test()
{
}
受到访问修饰符影响
嵌套类受到访问修饰符影响:
- public:外部可以用,通过
类名::类名
可以在外部使用嵌套类内容 - private:只能在外部类内部使用
- protected:只能在外部类内部和子类中使用
- public:外部可以用,通过
public 的嵌套类可以在外部直接声明对象来使用
private 和 protected 的嵌套类只能在
Outer
内部或其子类中使用
// Inner 如果是 public 的,可以在外部声明对象
Outer::Inner inner;
无限嵌套
- 嵌套类中可以再嵌套,理论上可以无限嵌套
- 使用时只需要通过
类名::类名::类名
往下嵌套使用即可
Outer::Inner::OuterInnerInner::OuterInnerInner2::OuterInnerInner3 q;
作用
- 封装:将与外部类强相关但不需要对外暴露的类隐藏在内部
- 辅助类:像外部类的“工具助手”
- 表达强依赖:表明“这个类仅用于这个类内部”的逻辑
- 总的来说,嵌套类一般和外部类都有密不可分的关系,如果没有这样的需求,不用强行使用
- 在日常开发中使用较少,根据需求选择使用即可
14.2 知识点代码
Outer.h
#pragma once
class Outer
{
public:
int i = 10;
//private:
//如果嵌套类是私有的就不能在外部使用了
class Inner
{
private:
int i = 10;
public:
float f = 4.5f;
void test();
//允许无限嵌套
class OuterInnerInner
{
public:
class OuterInnerInner2
{
public:
class OuterInnerInner3
{
};
};
};
protected:
double d = 5.5;
};
//可以有多个嵌套类
class Inner2
{
};
//Outer类有个Inner类的成员
Inner inner;
};
Outer.cpp
#include "Outer.h"
//我们在定义嵌套类中的成员时 需要明确它被谁包裹着
void Outer::Inner::test()
{
}
Lesson14_面向对象_封装_嵌套类.cpp
#include <iostream>
#include "Outer.h"
int main()
{
#pragma region 知识点一 嵌套类是什么
//嵌套类是指声明定义在一个类内部的类
//就像俄罗斯套娃一样,在类当中还有类的声明和定义
#pragma endregion
#pragma region 知识点二 嵌套类的声明和定义
//嵌套类的声明:
//直接在某一个类中(类语句块中)
//按照类声明语法进行声明
//嵌套类的定义:
//在宿主类中直接定义或在其cpp中进行定义
//定义时需要使用 类名::类名::成员名 这种形式明确属于哪一个类
//注意:
//嵌套类和外部类本质上是彼此独立的,嵌套类并不像外部类的成员那样紧密
//嵌套类和普通类使用上唯一的区别就是需要使用 类名::类名这种形式表明它是嵌套在一个类之中的
#pragma endregion
#pragma region 知识点三 受到访问修饰符影响
//嵌套类收到访问修饰符影响
//public:外部可以用,通过类名::类名可以在外部使用嵌套类内容
//private:只能内部用
//protected:只能内部和子类用
//public的就可以在外部直接声明对象来使用
//如果是私有和保护 只能在Outer内部使用 或子类使用
// Inner如果是pulic的 可以在外部声明Inner对象
Outer::Inner inner;
#pragma endregion
#pragma region 知识点四 无限嵌套
//嵌套类中可以再嵌套,理论上来说可以无限嵌套
//在使用时只需要通过 类名::类名::类名 往下嵌套使用即可
Outer::Inner::OuterInnerInner::OuterInnerInner2::OuterInnerInner3 q;
#pragma endregion
#pragma region 知识点五 作用
//1.封装
// 将与外部类强相关但不需要对外暴露的类隐藏在内部
//2.辅助类
// 像外部类的“工具助手”
//3.表达强依赖
// 表明“这个类仅用于这个类内部”逻辑
//等等
//总的来说,嵌套类一般和外部类都有密不可分的关系,如果没有这样的需求,不用强行使用
//它在日常开发时,使用较少,根据需求选择使用即可
#pragma endregion
}
14.3 练习题
嵌套类是否可以和外部的某个类重名?为什么?
可以重名。C++ 对嵌套类和外部类没有强制的命名限制,它们是完全独立的类型,互不影响。外部类通过 类名::嵌套类名
来引用,而在外部作用域可以直接用 嵌套类名
。唯一要注意的是,嵌套类的名字只能和非其宿主(enclosing)类重名。
#pragma once
#include <iostream>
using namespace std;
class Inner
{
public:
void test()
{
cout << "Inner" << endl;
}
};
#pragma once
#include "Inner.h"
#include <iostream>
using namespace std;
class Outer
{
protected:
int testI = 100;
public:
// 这是与外部同名的嵌套类 Inner
class Inner
{
private:
int testI = 99;
public:
void test()
{
cout << "Outer::Inner" << endl;
}
void SayHello();
// 嵌套类可以直接访问其宿主类的保护或私有成员
void PrintAInfo(Outer& o)
{
cout << o.testI << endl;
}
};
Inner i; // 默认引用的是 Outer::Inner
::Inner i2; // ::Inner 表示全局作用域下的 Inner
// 外部类无法访问嵌套类的私有或保护成员
void PrintInfo(Inner& i)
{
// cout << i.testI << endl; // 编译错误
}
};
#include "Inner.h"
#include "Outer.h"
#include <iostream>
using namespace std;
void Outer::Inner::SayHello()
{
cout << "你好呀" << endl;
}
Inner i; // 全局作用域的 Inner
Outer::Inner i2; // Outer::Inner
Outer o;
o.i.test(); // 输出:Outer::Inner
o.i2.test(); // 输出:Inner
嵌套类对象的创建与调用
给定以下嵌套类定义:
class Outer {
public:
class Inner {
public:
void SayHello();
};
//不加 那么默认就是我们内部的这个嵌套类 就是局部去查找的感觉
Inner i;
};
可以这样创建并调用 SayHello()
:
Outer o2;
o2.i.SayHello(); // 如果 Outer 中有成员 i
Outer::Inner i3;
i3.SayHello(); // 在外部直接实例化并调用
嵌套类访问宿主类私有成员的问题
class A {
private:
int x = 100;
public:
class B {
public:
void PrintX(A& a) {
std::cout << a.x << std::endl;
}
};
};
这段代码没有问题。C++ 中嵌套类可以访问其宿主类的私有成员,因为它们处于同一个作用域:
A a;
A::B b;
b.PrintX(a); // 输出 100
14.4 练习题代码
Inner.h
#pragma once
#include <iostream>
using namespace std;
class Inner
{
public:
void test()
{
cout << "Inner" << endl;
}
};
Outer.h
#pragma once
#include "Inner.h"
#include <iostream>
using namespace std;
class Outer
{
//private:
protected:
int testI = 100;
public:
class Inner
{
private:
int testI = 99;
public:
void test()
{
cout << "Outer::Inner" << endl;
}
void SayHello();
//C++中嵌套类 可以直接访问外部宿主类的私有或保护成员,因为他们在同一个作用域当中
void PrintAInfo(Outer& o)
{
cout << o.testI << endl;
}
};
//不加 那么默认就是我们内部的这个嵌套类 就是局部去查找的感觉
Inner i;
//::代表全局作用域 这是使用外部的Inner类
::Inner i2;
//外部的类想要访问 嵌套类中的私有或保护是无法访问的
void PrintInfo(Inner& i)
{
//cout << i.testI << endl;
}
};
Outer.cpp
#include "Outer.h"
#include <iostream>
using namespace std;
void Outer::Inner::SayHello()
{
cout << "你好呀" << endl;
}
Lesson14_练习题.cpp
#include <iostream>
#include "Outer.h"
#include "Inner.h"
int main()
{
#pragma region 练习题一
//嵌套类是否可以和外部的某个类重名?为什么?
//
//
//可以重名
//嵌套类和外部类之间C++并没有强制命名限制
//他们都是独立的类型,不会相互影响
//类名::类名
//类名
//需要注意:只能和非宿主类重名
Inner i;
Outer::Inner i2;
Outer o;
o.i.test();//Outer::Inner
o.i2.test();//Inner
#pragma endregion
#pragma region 练习题二
/*class Outer {
public:
class Inner {
public:
void SayHello();
};
};
请写出以上嵌套类的对象创建方式,并调用 SayHello() 方法*/
Outer o2;
o2.i.SayHello();//你好呀
//在外部实例化一个嵌套类对象 然后去调用方法
Outer::Inner i3;
i3.SayHello();//你好呀
#pragma endregion
#pragma region 练习题三
/*class A {
private:
int x = 100;
public:
class B {
public:
void PrintX(A& a) {
std::cout << a.x << std::endl;
}
};
};
以上代码,是否存在问题,应该如何修改?*/
//这的代码 没有问题 不会报错
//争议点:嵌套类能不能使用宿主类的私有内容,答案是可以用
// C++中嵌套类 可以直接访问外部宿主类的私有成员,因为他们在同一个作用域当中
i3.PrintAInfo(o);//100
#pragma endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com