当前位置: 首页 > news >正文

【C++】类和对象(三)

目录

1 初始化列表

2 类型转换

3 static成员

4 友元

5 内部类

6 匿名对象


1 初始化列表

构造函数的初始化除了在函数体内赋值,还有另一种方式,就是初始化列表。初始化列表使用时是以一个冒号开始,接着加逗号来分割数据成员列表。每个成员变量后面放括号,括号里放初始值或者表达式。根据一段代码举例

class Date
{
public:Date(int& x, int year, int month, int day):_year(year)   //初始化列表, _month(month), _day(day){}void Print()const{cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day;
};

每个成员变量在初始化列表中只能出现一次,初始化列表可以看做是每个成员变量定义初始化的地方

注意,成员变量是引用成员变量const成员变量没有默认构造的类类型变量必须放在初始化列表位置进行初始化,否则会编译报错。

C++11支持在成员变量声明的位置给缺省值,缺省值主要是给没有显示在初始化列表的初始化成员使用的。

举例说明:

class Time
{
public:Time(int hour):_hour(hour){}
private:int _hour;
};
class Date
{
public:Date(int& x, int year, int month, int day):_year(year), _month(month), _t(2), _ref(x), _n(1){}void Print()const{cout << _year << "/" << _month << "/" << _day << endl;}
private:int _year;int _month;int _day=1;//缺省值Time _t;//没有默认构造的成员变量int& _ref;//引用成员变量const int _n;//const成员变量
};

无论是否写初始化列表,每一个构造函数都有初始化列表。尽量使用初始化列表初始化,因为每个成员变量都会走初始化列表,即使这个成员变量不在初始化列表中。如果成员变量在声明位置给了缺省值,初始化列表没有这个成员变量,会用这个缺省值初始化。

如果成员变量既没有给缺省值,又没有在初始化列表初始化,对于内置类型成员是否初始化取决于编译器,C++没有单独规定。对于自定义类型成员会调用这个成员类型的默认构造函数,如果没有默认构造函数会编译错误。

以下为初始化流程:

初始化列表中按照成员变量在类中的声明顺序进行初始化,跟初始化列表中成员出现的先后顺序没关系。建议初始化列表数据和声明顺序保持一致。看个例子:
 

#include<iostream>
using namespace std;
class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2 = 2;int _a1 = 2;
};
int main()
{A aa(1);aa.Print();
}

由于初始化列表中按照成员变量在类中的生命顺序进行初始化,所以_a2先初始化,此时_a1没有初始化,所以_a2打印出来是随机值,_a1为1。

2 类型转换

  • C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。
  • 类类型的对象之间也支持隐式类型转换,需要相应的构造函数支持。
  • 只要在构造函数前加explicit,就不支持隐式类型转换。

下面举个例子,有相应注释说明:

#include <iostream>
using namespace std;
class A
{
public:A(int a):_a1(a),_a2(_a1){ }
private:int _a1;int _a2;
};
int main()
{//构造A aa1(1);//隐式类型转换,由整型转换成A类型,用2构造一个临时对象,再用临时对象拷贝构造//编译器会优化,会直接构造A aa2 = 2;//这样是错误的,2会产生一个临时对象,临时对象具有常性//A& aa3 = 2;//正确写法const A aa3 = 2;
}

3 static成员

  • 用static修饰的成员变量,称之为静态成员变量,静态成员变量要在类外进行初始化。
  • 静态成员变量存放在静态区,为所有类对象所共享,不属于某个具体的对象。
  • 静态成员函数没有this指针。
  • 静态成员函数可以访问其他的静态成员,但是不能访问非静态的,因为没有this指针
  • 非静态的成员函数,可以访问任意的静态成员变量和静态成员函数
  • 静态成员也是类的成员,受public、protected、private访问限定符的限制。
  • 静态成员变量不属于某个对象,不走初始化列表初始化。不能在声明位置给缺省值初始化。
// 实现⼀个类,计算程序中创建出了多少个类对象
#include<iostream>
using namespace std;
class A
{
public:A(){++_count;}A(const A& t){++_count;}~A(){--_count;}static int GetACount(){return _count;}
private:// 类⾥⾯声明static int _count;
};
// 类外⾯初始化
int A::_count = 0;
int main()
{cout << A::GetACount() << endl;//0A a1, a2;A a3(a1);cout << A::GetACount() << endl;//3cout << a1.GetACount() << endl;//3return 0;
}

4 友元

友元提供了突破类访问限定符的方式,友元分为友元函数和友元类,使用方式是在函数声明或者类声明前面加friend,并且把友元声明放在一个类的里面。

外部的友元函数可以访问类的私有和保护成员,这是友元的作用。

#include<iostream>
using namespace std;
// 前置声明
class B;
class A
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _a1 = 1;int _a2 = 2;
};
class B
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _b1 = 3;int _b2 = 4;
};
void func(const A& aa, const B& bb)
{cout << aa._a1 << endl;cout << bb._b1 << endl;
}
int main()
{A aa;B bb;func(aa, bb);//输出1  3return 0;
}
  • 一个函数可以是多个类的友元函数。
  • 友元类的关系是单向的,A类是B类的友元,B类不是A类的友元。
  • 友元类关系不可以传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
  • 友元会增加耦合度,破坏了封装,友元不宜多用。

5 内部类

如果一个类定义在另一个类的内部,这个类就叫做内部类。内部类是一个独立的类,外部的类实例化的对象不包含内部类

内部类默认是外部类的友元类

如果把内部类放在private或protected位置,那么这个内部类就是专属内部类,其余地方用不了。


#include<iostream>
using namespace std;
class A
{
private:int _k=1;int _h = 1;
public:class B // B默认就是A的友元{public:void f(const A& a){cout << a._k << endl;  //可以调用A的成员变量        cout << a._h << endl;     }int _b1;};
};
int main()
{A::B b;A aa;b.f(aa);//输出1 1return 0;
}

6 匿名对象

利用类型(实参)这样格式定义出来的对象是匿名对象,匿名对象的生命周期只有当前一行,过了这行就结束了。像类型 对象名(实参)这样格式定义出来的是有名对象

#include<iostream>
using namespace std;
class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};
class Solution 
{
public:int Sum_Solution(int n) {return n;}
};
int main()
{A aa1;// 定义匿名对象,匿名对象的特点不⽤取名字,// ⽣命周期只有这⼀⾏,下⼀⾏他就会⾃动调⽤析构函数  A();A(1);A aa2(2);// 匿名对象在这样场景下就很好用,不用单独写一行去实例化新对象cout << Solution().Sum_Solution(10)<<endl;return 0;
}

以上就是本文全部内容了,主要说明类和对象中的各个小知识点,如果这篇文章对你有用,可以点点赞哦,你的支持就是我写下去的动力,本文是类和对象的最后一篇文章,后续会继续更新其他知识。


文章转载自:

http://7OEbCwAv.pmwhj.cn
http://nJy53Aez.pmwhj.cn
http://3XtMvUef.pmwhj.cn
http://E8dPJ3p7.pmwhj.cn
http://S2h10azT.pmwhj.cn
http://CqT6yKfA.pmwhj.cn
http://0Of6DLHo.pmwhj.cn
http://Pt4cT40H.pmwhj.cn
http://6MU3KDe1.pmwhj.cn
http://7ZQTn4P6.pmwhj.cn
http://3b45I52L.pmwhj.cn
http://p4GiD7eB.pmwhj.cn
http://99uJu6GC.pmwhj.cn
http://131H7Hu5.pmwhj.cn
http://NYoGbW6s.pmwhj.cn
http://hU5jFrh1.pmwhj.cn
http://VwXn6uue.pmwhj.cn
http://3lMEJJMg.pmwhj.cn
http://ZjnHgWZx.pmwhj.cn
http://xL8YJjRM.pmwhj.cn
http://a0egI4fh.pmwhj.cn
http://BYy8GUS0.pmwhj.cn
http://FtfgJOU3.pmwhj.cn
http://tkIeUXwF.pmwhj.cn
http://dCnxulDx.pmwhj.cn
http://wO69HZHs.pmwhj.cn
http://dQRC51jI.pmwhj.cn
http://1g5I37yD.pmwhj.cn
http://YcM1Qtx4.pmwhj.cn
http://d8ocqY6f.pmwhj.cn
http://www.dtcms.com/a/369871.html

相关文章:

  • 【面试向】人工智能机器学习介绍
  • 轻量级XML读写库Mini-XML的编译和使用
  • 【数论】P10580 [蓝桥杯 2024 国 A] gcd 与 lcm|普及+
  • 微服务的编程测评系统22-项目部署结束
  • DNS解析中的服务器协作机制
  • Windows权限提升(二)
  • Homebrew执行brew install出现错误(homebrew-bottles)
  • 数据结构之二叉树(1)
  • Vue 3项目中引用ECharts并设计多种图表组件的实现方案
  • Day37 MQTT协议 多客户端服务器模型
  • 【UAV】基于PX4+Ubuntu24.04.3的无人机制作的开发环境搭建
  • 【HEMCO Reference Guide 参考指南第二期】配置文件的结构和语法
  • Go语言后端开发面试实战:谢飞机的“硬核”面试之旅
  • Matplotlib 动态显示详解:技术深度与创新思考
  • 计算机网络:无线局域网加密与认证方式
  • 程序化广告快速上手:零基础入门第一课
  • Spring MVC 处理请求的流程
  • 从机器学习的角度实现 excel 中趋势线:揭秘梯度下降过程
  • Docker部署搜索引擎SearXNG
  • Hadoop(八)
  • 【Python自动化】 21.2 Pandas 读取 Excel 时的 dtype 参数完全指南
  • 【面板数据】各省制造业出口技术复杂度数据集(2010-2023年)
  • 使用 YAML 自动化 Azure DevOps 管道
  • 【数据库相关】TxSQL新增数据库节点步骤
  • 理想汽车智驾方案介绍 4 World model + 强化学习重建自动驾驶交互环境
  • 大语言模型预训练数据采集与清洗技术实践:从语料到知识库的全流程优化
  • 腾讯混元翻译模型Hunyuan-MT-7B开源,先前拿了30个冠军
  • MiniDrive:面向自动驾驶的更高效的视觉语言模型
  • 2025年渗透测试面试题总结-54(题目+回答)
  • 《Kubernetes 构建 MySQL MGR 集群实战教程》