个人主页:Jason_from_China-CSDN博客
所属栏目:C++系统性学习_Jason_from_China的博客-CSDN博客
所属栏目:C++知识点的补充_Jason_from_China的博客-CSDN博客
概念概述
- 如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
- 内部类默认是外部类的友元类。
- 内部类本质也是一种封装,当 A 类跟 B 类紧密关联,A 类实现出来主要就是给 B 类使用,那么可以考虑把 A 类设计为 B 的内部类,如果放到 private/protected 位置,那么 A 类就是 B 类的专属内部类,其他地方都用不了。
内部类的使用1
正常代码
class A { public: A(); ~A(); private: }; class B { public: B(); ~B(); private: };
内部类的代码
#include<iostream> using namespace std; class A { public: A(int a1 = 1, int a2 = 1) :_a1(a1) ,_a2(a2) {}; class B { public: //错误写法,内部类和外部类是相对独立的,是不能直接访问的 //B(int b1 = _a1, int b2 = _a2) //B() //{} 直接访问类(这里没有默认构造) //B(const A a) // :_b1(a._a1) // ,_b2(a._a2) //{} //默认构造写法 B(int b1 = 2, int b2 = 2) :_b1(b1) ,_b2(b2) {} void _print() { cout << "内部类默认是外部类的友元函数" << endl; } private: int _b1; int _b2; }; private: int _a1 = 1; int _a2 = 1; }; int main() { A a; A::B b; return 0; }
注意事项:
- 内部类和外部类是相对独立的,外部类构造时,不能直接将构造的数值传递给内部类。外部类先构造,但在外部类构造函数执行时,内部类的对象可能还未创建,内部类的作用域在外部类内部,外部类构造函数不能直接访问还未创建的内部类对象的成员。
下图我们就可以看出来,我们直接从外部类构造的数值去初始化内部类是不能成功的,需要默认构造函数但是我们加上默认构造是可以的,说明,内部类和外部类是相对独立的
- 内部类默认是外部类的友元函数(内部类的调用受到访问限定符的限制)
这里我们发现A类,突破类域就可以访问B,但是B不能说突破类域访问A
- 如果你需要把外部类的构造给内部类使用,那么我们可以采取get成员函数的方式,或者静态成员变量的方式来进行使用
#include<iostream> using namespace std; class A { public: A(int a1 = 1, int a2 = 1) :_a1(a1) ,_a2(a2) {}; int geta1() { return _a1; } class B { public: //直接访问类(这里没有默认构造)(可以接收参数) B(const A a) :_b1(a._a1) ,_b2(a._a2) {} //默认构造写法 B(int b1 = 2, int b2 = 2) :_b1(b1) ,_b2(_b2) {} private: int _b1; int _b2; }; private: int _a1 = 1; int _a2 = 1; }; int main() { A a; int ret1 = a.geta1(); A::B b = { ret1 }; return 0; }
内部类的使用2:
没有学习之前:
这里我使用vs编译器,vs编译器不支持可边长数组,所以代码有点不一样
#include<iostream> using namespace std; //求1+2......+n//不能使用乘除 class sum { public: sum() { _ret += _i; ++_i; } //获取ret最终的结果 static int _GetRet() { return _ret; } private: static int _i; static int _ret; }; int sum::_i = 1; int sum::_ret = 0; class solution { public: int _solution(int n) { for (int i = 0; i < n; i++) { //创建n次构造函数,n次构造函数++会依次递加 sum s; } //创建n次数之后,我们计算出来数值,此时我们可以选择数值来进行接收 int ret = sum::_GetRet(); //打印数值 cout << ret << endl; //返回数值 return sum::_GetRet(); } }; int main() { solution s; int ret = s._solution(100);//这里接收进行验证,发现是正确的 cout << ret << endl;//打印出来 return 0; }
类
sum
成员变量:
static int _i
:静态成员变量,用于记录当前要累加的数字。初始化为 1。static int _ret
:静态成员变量,用于存储累加的结果。初始化为 0。构造函数:
- 每次创建
sum
类的对象时,构造函数被调用。在构造函数中,将当前的_i
值累加到_ret
中,然后将_i
的值自增。这样,每次创建对象就相当于进行一次累加操作。静态成员函数
_GetRet()
:
- 用于获取
_ret
的值,即累加的结果。类
solution
- 成员函数
_solution(int n)
:
- 这个函数接受一个整数
n
,目的是计算从 1 加到n
的和。- 通过一个循环创建
n
次sum
类的对象。每次创建对象时,sum
类的构造函数会自动进行累加操作。- 最后,通过
sum::_GetRet()
获取累加的结果,并将其赋值给ret
,然后打印和返回这个结果。学习之后:
这里采取的是vs编译器,vs编译器是不支持可变长数组的,所以代码有点出入
#include<iostream> using namespace std; class sol { //内部类 class Sum { public: Sum() { _ret += _i; ++_i; } static int _i; static int _ret; }; public: static int _sol(int n) { for (size_t i = 0; i < n; i++) { Sum s; } //这里不需要成员函数了,直接可以访问私有变量 return Sum::_ret; } }; //这里需要注意一下,因为我们需要突破类域 int sol::Sum::_i = 1; int sol::Sum::_ret = 0; int main() { sol s; int ret = s._sol(100); cout << ret << endl; return 0; }