构造函数、友元、static等
1.再谈构造函数(见上篇)尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
成员变量初始化的真正次序与与成员变量在类中的的声明先后次序一致,与其在初始化列表中的先后次序无关。
构造函数还有另外一个作用:
Date d1(2020);
d1=1901;
对于(d1=1901),1.使用1901作为参数调用单参构造函数创建一个匿名对象,2.使用创建的匿名对象给d1进行赋值;3.匿名对象销毁掉;
对于单个参数的构造函数,还具有类型转换的作用。
这种操作代码可读性不高,用explicit修饰构造函数,将会禁止单参构造函数的隐式转换;
2.static成员
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化。
不属于摸一个具体的类对象;与对象无关,是类的成员;不会存储在对象中,也不会影响sizeof的结果;
静态成员变量在类中只是声明,必须在类外进行定义,在变量前加类名::
不能在构造函数初始化列表的位置来进行初始化;
访问方式:类名::静态成员变量(推荐) 、对象.静态成员变量;
静态成员函数---本质:和对象无关--也可以不通过对象调用;
对象.Getcount() 《---》类名::GetCount()底层处理完全相同没有this指针;
不能访问非静态的成员变量---只能访问静态成员变量;
不能直接调用非静态类型的成员函数-->非静态类型的成员函数有一个隐藏的this指针参数,无法传递;
只能调用与对象无关的方法---》只能直接调用类中静态的成员函数;
静态成员函数-----》调用约定:_cdecl
通过类名访问成员函数(带有静态成员变量)要用静态成员函数;
static:不能修饰构造函数、拷贝构造、赋值运算符重载、析构函数、虚函数;
3.友元
<<重载的规则:第一个必须是ostream&,第二个参数才是打印的内容;
友元分为:友元函数和友元类友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
问题:现在我们尝试去重载operator<<,然后发现我们没办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以我们要将operator<<重载成全局函数。但是这样的话,又会导致类外没办法访问成员,那么这里就需要友元来解决。operator>>同理。
class Date{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
ostream& operator<<(ostream& _cout)
{_cout<<d._year<<"-"<<d._month<<"-"<<d._day;return _cout;
}
prvate:
int _year;int _month;int _day
};int main()
{
Date d(2017, 12, 24);
d<<cout;
return 0;} 友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
说明:友元函数可访问类的私有和保护成员,但不是类的成员函数;
友元函数不能用const修饰;
友元函数可以在类定义的任何地方声明,不受类访问限定符限制;
一个函数可以是多个类的友元函数;
友元函数的调用与普通函数的调用和原理相同;
友元类:
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。友元关系是单向的,不具有交换性。
比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
友元关系不能传递、友元关系不能继承;
如果B是A的友元,C是B的友元,则不能说明C时A的友元。
4.内部类
概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。注意:内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
特性:
1. 内部类可以定义在外部类的public、protected、private都是可以的。
2. 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。
3. sizeof(外部类)=外部类,和内部类没有任何关系。
文档来源:51CTO技术博客https://blog.51cto.com/u_15152976/3035601
页:
[1]