前言
本篇文章接类和对象——下-CSDN博客
这次主要讲解内置类型与自定义类型的转换,加上一些友元函数,友元类的讲解。
回顾:
在上一篇文章中我们了解了运算符重载的规则,第一个传入参数为运算左值,第二个为右值,并且为了实现可以多次运算,我们进行了对cout的返回。
还有const函数的权限问题,对const修饰的类进行函数传参,要注意权限的问题,而权限只能缩小和平移。
初始化列表的最大作用就是解决了像const修饰的对象,引用等声明和初始化分离的问题。
一、类型转换
在我们初学c++的时候我们也学习了一些基础的数据类型的转换,现在,我们来深入学习下数据类型的转换:
下面代码:
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year=1, int mouth=1, int day=1)
:_year(year)
, _mouth(mouth)
, _day(day)
{
cout << _year << '/' << _mouth << '/' << _day << endl;
}
private:
const int _year;
int _mouth;
int _day;
};
int main()
{
Date s1=(2023,11,4);
Date s2 = { 2023,11,4 };
}
你觉得s1和s2的初始化结果是什么?
我们对s2进行初始化的时候,首先会将传入的数据进行隐式类型转换,将其转换为Data类对象,然后根据Data类中的构造函数进行初始化。(当我们对s2使用2023,11,4进行初始化的时候,这里的数据会和类中的构造函数进行参数匹配,只有当构造函数中拥有这个类型的参数时,才能进行隐式类型转换。)所以能否初始化,其决定因素为类中的构造函数的参数是什么。
为什么s1的初始化结果年是4,而其他的是缺省值。
这里的原因其实是因为s1的初始化使用了逗号表达式,而逗号表达式的最后一个值是表达式的结果,这也导致了只有year进行了初始化,而s2才是正确的初始化方法,
那么这里初始化的原理是什么呢?
当我们在花括号中放入参数传给构造函数的时候其实,这些传入参数发生了隐式类型的转换,这里的三个整形数据被转换成了一个日期类,而后使用转换后的日期类进行初始化,这就是这里初始化的全过程。
当然,如果我们并不想要这个隐式类型转换发生,我们也可以禁止它,这里就使用到了explicit,当我们在类中的构造函数前加上explicit,这样就不会发生隐式类型转换了
#include<iostream>
using namespace std;
class Date
{
public:
explicit Date(int year = 1, int mouth = 1, int day = 1)
:_year(year)
, _mouth(mouth)
, _day(day)
{
cout << _year << '/' << _mouth << '/' << _day << endl;
}
private:
const int _year;
int _mouth;
int _day;
};
int main()
{
Date s1 = (2023, 11, 4);
Date s2 = { 2023,11,4 };
}
二、友元函数
在上一篇文章中我们浅浅的讲述了关于友元函数的使用,现在我们来更加详细的了解友元函数。
在友元函数中,友元函数这个东西是针对类来说的,你可以把它理解为你和你兄弟的关系
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int mouth = 1, int day = 1)
:_year(year)
,_mouth(mouth)
,_day(day)
{
cout << _year << '/' << _mouth << '/' << _day << endl;
}
friend void Funk(Date s1);
private:
int _year;
int _mouth;
int _day;
};
void Funk(Date s1)
{
cout << s1._year << endl;
}
int main()
{
Date s1 = { 2023,11,4 };
}
但是我们并不推荐大量的使用友元函数,这样会使类的数据跟公开的一样。
三、友元类
我们说完友元函数之后,再来说下友元类,同友元函数一样,友元类指的是类和类的关系,这样又有了类中类,和两个单体类的分别,先来说说两个单体类,
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int mouth = 1, int day = 1)
:_year(year)
,_mouth(mouth)
,_day(day)
{
cout << _year << '/' << _mouth << '/' << _day << endl;
}
friend class Date_1;
private:
int _year;
int _mouth;
int _day;
};
class Date_1
{
public:
Date_1()
{
Date s{ 2023,11,4 };
}
void Print()
{
cout << s._year << endl;
}
private:
Date s;
};
int main()
{
Date_1 s1;
s1.Print();
}
我们将Date_1声明为Date的友元类,这时我们就可以访问Date的私有数据,这就是两个单独的类。
但是友元是单向的,意思就是我把你当兄弟你把我踹沟里的样子,A对B是友元类,A可以访问B,但是B不能访问A。
接下来我们来看类中类:
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int mouth = 1, int day = 1)
:_year(year)
,_mouth(mouth)
,_day(day)
{
cout << _year << '/' << _mouth << '/' << _day << endl;
}
class Date_1
{
public:
Date_1()
{
}
void Print()
{
Date a;
cout << a._year << endl;
}
private:
int a;
};
内部类天生就是外部类的友元,但是外部类是无法访问内部类的数据的。
总结
本篇重要的是类型转换的内容,友元方面比较简单,类型转换关于自定义类型需要匹配类中的构造函数进行隐式类型转换,如果构造函数中没有匹配参数则无法初始化,如果想阻止隐式转换,那么就在构造函数前加上explicit,用以阻止隐式转换。