当前位置:网站首页>类和对象收尾
类和对象收尾
2022-07-01 03:38:00 【__cplusplus】
本文主要内容:
- 初始化列表
- 静态成员,成员函数
- 友元
1.初始化列表
今天我们来进行类和对象的收尾,相比于前面的构造函数和析构函数来说,这篇文章的内容相对是比较好理解的。我们这篇博客就来提一提静态成员,成员函数还有前面稍微提到的初始化列表。
所谓的初始化列表就是成员变量被定义的地方!你可能会有疑问,在构造一个对象的时候,整个对象都出来了,为什么还要特意给成员变量找一个定义的地方。有这个疑问是很正常的。来看看下面这段代码:
class Demo
{
private:
int _a;
const int _b;//const常量必须在定义的时候初始化
int& _rc;//引用也必须在定义的时候初始化
};
正是因为有的类的成员变量必须在定义的时候就要初始化,所以才必须找一个定义的地方。而成员定义的地方正好就是初始化列表,所以这个Demo类的构造函数可以这么写:
class Demo
{
public:
Demo(int a=4)
: _a(4)
, _b(3)
, _rc(a)
{
}
private:
int _a;
const int _b;
int& _rc;
};
也就是说,每一次调用构造函数,所有的成员变量都会走一次初始化列表。不仅如此,初始化列表还可以应用在下面这种情况:
//初始化列表解决无法生成默认构造函数的问题
class A
{
public:
A(int x)
{
_x = x;
}
private:
int _x;
};
class Demo
{
public:
Demo(int a=4)
: _a(4)
, _b(3)
, _rc(a)
,_aa(5)
{
}
private:
int _a;
const int _b;
int& _rc;
A _aa;
};
本来正常情况下,我们是没有办法提供Demo类的默认构造函数,因为类A没有默认构造函数,但是利用初始化列表我们就可以很好解决这个问题。
另外,初始化列表的初始化顺序只和类成员的声明顺序有关,而和初始化顺序无关
class B
{
public:
B()
:_b1(4)
,_b2(_b1)
{
}
private:
int _b2;
int _b1;
};
int main()
{
B b;
return 0;
}
打开监视窗口,观察到如下的信息:
如果初始化列表里面的顺序来看,最后_b1,_b2的值应该都被初始化成4,但是很明显这里的_b2却是随机值。因为初始化列表的初始化是按照成员声明的顺序来的!所以说这里先用_b1初始化_b2,因此_b2是随机值!在使用初始化列表的时候要特别注意这一点。
2.静态成员,静态成员函数
前面我们类所拥有的成员都是依赖于实例化对象的。那么在C++里面还提供了一种特殊的机制---->静态成员,静态成员函数,那么这两个东西是不需要依赖对象---->可以理解成,静态成员和静态成员函数为所有类对象所共有的。
我们可以来看一看具体的静态成员怎么定义:
class C
{
private:
int _a;
static char _c;
};
那么静态成员的初始化比较特殊,由于静态成员的特殊性,因此静态成员并不会在初始化列表定义。我们必须显式自己初始化静态成员。
//这里为了演示,把静态成员放出来
class C
{
private:
int _a;
public:
static char _c;
};
//静态成员必须类外初始化,因为静态成员不会走初始化列表
C::_c=1;
讲完了静态成员,我们在来看看静态成员函数,语法声明也是在成员函数前面加一个static关键字。
class Demo
{
public:
//这就是一个静态的成员函数
static void show()
{
cout<<"hello world!"<<endl;
}
};
访问静态成员函数的方法有两种:
1.使用实例化对象访问
2.使用类名::函数名进行访问
思考两个问题:
1.普通成员函数能否调用静态成员函数?
2.静态成员函数能否调用普通成员函数?
答案是:普通成员函数可以调用静态成员函数,而静态成员函数不能普通成员函数。因为,静态成员函数没有this指针!
3.友元
以日期类为例,有的时候我们希望通过键盘输入来构造日期类对象,那么我们就需要对日期类进行流提取运算符的重载,假如我们把流提取运算符重载成成员函数
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
}
Date& operator=(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
//标准库流对象
istream& operator>>(istream& in)
{
in>>_year>>_month>>_day;
return in;
}
private:
int _year;
int _month;
int _day;
};
//具体调用
int main()
{
Date d1;
//cin>>d1是错误的
d1>>cin;//这个是正确调用!
return 0;
}
出现这种情况的原因就是:两个操作数的函数,编译器会自动把左操作数作为第一个参数。而成员函数的第一个参数永远是this指针,我们没办法更改!所以为了我们能够写法更加自然和易于理解,最好能重载全局的流提取运算符。但是又有一个问题。私有的成员变量外部无法直接访问。因此C++提供了一种特殊的机制来解决---->友元
我们先来看一看怎么使用友元来使得访问私有成员:
class Date
{
public:
//友元声明---->friend关键字
friend istream& operator>>(Date& d);
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
}
Date& operator=(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};
//重载全局的流提取
istream& operator(Date& d)
{
in>>d._year>>d._month>>d._day;
return in;
}
经过上面的操作以后,我们就可以使用cin来提取日期类的信息了!
友元有以下几个注意的地方:
- 友元关系是单向的,A是B的友元,但是B的友元不是A!
- 友元没有传递性!
- 友元会破坏封装,尽量避免使用友元
总结
- 初始化列表是成员定义的地方
- 静态成员,函数是属于类的,静态成员函数没有this指针
- 友元的简单使用
本文的主要内容就到这里,如有不足支持还望指出,希望大家一起共同进步!
边栏推荐
- 【TA-霜狼_may-《百人计划》】1.2.2 矩阵计算
- MFC窗口滚动条用法
- Unexpected token o in JSON at position 1 ,JSON解析问题
- [TA frost wolf _may - "hundred people plan"] 1.4 introduction to PC mobile phone graphics API
- Promql select time series
- jeecgboot输出日志,@Slf4j的使用方法
- Processing of menu buttons on the left and contents on the right of the background system page, and double scrolling appears on the background system page
- 30. 串联所有单词的子串
- 浏览器顶部loading(来自知乎)
- How keil displays Chinese annotations (simple with pictures)
猜你喜欢
![[TA frost wolf \u may- hundred people plan] 2.3 introduction to common functions](/img/be/325f78dee744138a865c13d2c20475.png)
[TA frost wolf \u may- hundred people plan] 2.3 introduction to common functions

Use of comment keyword in database

Jeecgboot output log, how to use @slf4j
![4. [WebGIS practice] software operation chapter - data import and processing](/img/5a/b86e0538660f27c809cf429053a06c.png)
4. [WebGIS practice] software operation chapter - data import and processing

Error: plug ins declaring extensions or extension points must set the singleton directive to true

Complete knapsack problem

jeecgboot输出日志,@Slf4j的使用方法
![5. [WebGIS practice] software operation - service release and permission management](/img/5d/070e207bd96e60ba1846d644d4fb54.png)
5. [WebGIS practice] software operation - service release and permission management

Unity之三维空间多点箭头导航

JMeter login failure, extracting login token, and obtaining token problem solving
随机推荐
Why can't you find the corresponding function by clicking go to definiton (super easy has a diagram)
【TA-霜狼_may-《百人计划》】2.4 传统经验光照模型
Jenkins自动清理构建历史
Cygwin的下载和安装配置
205. 同构字符串
Unexpected token o in JSON at position 1, JSON parsing problem
171. Excel 表列序号
整合阿里云短信的问题:无法从静态上下文中引用非静态方法
5. [WebGIS practice] software operation - service release and permission management
Redis(七)优化建议
6. zigzag transformation
程序员女友给我做了一个疲劳驾驶检测
392. 判断子序列
idea插件备份表
HoloLens2开发环境搭建及部署app
Usage of AfxMessageBox and MessageBox
JMeter学习笔记2-图形界面简单介绍
241. Design priorities for operational expressions
Error: plug ins declaring extensions or extension points must set the singleton directive to true
Use of comment keyword in database