第一部分的链接:https://mp.csdn.net/mdeditor/89046994#
1.C++11 的成员初始化新玩法
c++11在定义变量成员的时候,可以在定义直接初始化。
看下面的一段代码:
class B
{
public:
B(int b = 0)
:_b(b)
{}
public:
int _b;
};
class A
{
public:
void Print()
{
cout << _a << endl;
cout << b._b << endl;
cout << n << endl;
}
private:
int _a = 10;
B b = 20;
//int* p = (int*)malloc(sizeof(int)*4);
static int n;
};
int A::n = 30;
int main()
{
A a;
a.Print();
return 0;
}
对了 在定义的时候,一定要记住,在定义B类时候,一定要把上面的定义成public类型;这样下面才能调用。
2.友元
友元分为:友元函数和友元类;
(1)友元函数
class Date
{
public:
Date(int year = 1990, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{}
ostream& operator<<(ostream& _cout)
{
_cout << _year << "-" << _month << "-" << _day <<endl;
return _cout;
}
private:
int _year;
int _month;
int _day;
};
int main(){
Date d1;
//cout << d1; //这种在实现的时候不能通过,但是这种是我们常用的实现方式
d1 << cout;
return 0;}
**实现上面的一段代码,现在我们想重载<<这个符号,但是执行代码之后发现我们不能不能重载,这是为什么呢?**因为,cout输出流和隐藏的this指针在抢占第一的位置,this指针默认第一个参数也就是左操作数,但是实际中使用cout是第一形参对象,才能正常使用,所以我们要将operator<<重载为全局函数,但是这样的话,又无法访问类外面的成员函数,所以,我们现在要将使用友元函数,来解决这样的问题。
下来,我们看下面的一段代码,
class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
public:
Date(int year = 2019, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator << (ostream& _cout ,const Date& d)
{
_cout <<d._year << "-" << d._month << "-" << d._day << endl;
return _cout;
}
int main()
{
Date d;
cout << d <<endl; //这样我们就可以使使用我们能够理解的代码
//d1 << cout;
return 0;
}
这样就通过友元函数的使用,我们就解决了这个问题。
说明:
(1)友元函数可访问类的私有成员,但不是类的成员函数
(2)友元函数不能用const修饰
(3)友元函数可以在类定义的任何地方声明,不受类访问限定符限制
(4)一个函数可以是多个类的友元函数
(5)友元函数的调用与普通函数的调用和原理相同
我们通过学习使用重载operator<<来实现友元函数的调用,我们还可以实现一下:istream>>输入流的重载,这个我就不实现了,下来可以自己实现,调用的原理相同,但是在输入流的时候,要每一个成员函数都要输入,不是向输出一样,一次下都输出了。
(2) 友元类
友元类的的所有成员函数都是另外一个类的友元函数,都可以访问另一个类中的非公有成员。
1.友元关系单项的,不具有交换性。
比如说:上面的Time类和Date类,在Time类中声明Date类为基友元类,那么可以在其Date类中可以访问Time类的私有成员,反之,Time类想访问Date类的私有成员,不可以。
2.友元关系不能传递。
比如说,B是A的友元,C是B的友元,则不能说明C是A的友元。
#include<iostream>
using namespace std;
class Date;
class Time
{
friend class Date;
public:
Time(int hour = 12, int minute= 38, int second = 48)
:_hour(hour)
, _minute(minute)
, _second(second)
{}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year = 1990, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{
cout << _year <<"-"<< _month <<"-"<< _day << endl;
}
void SetTimeofDate(int hour, int minute, int second)
{
_t._hour = hour;
_t._minute = minute;
_t._second = second;
_t._minute = minute;
cout << _t._hour << "-" << _t._minute << "-" << _t._second << endl;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
int main()
{
Date d1(2019,4,8);
//d1.SetTimeofDate(12,45,32);
return 0;
}
就像上面的代码,你敲一下,就可能明白其中的道理,与上面的文字相结合;
3.内部类
(1)概念及特征
概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。
注意:内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
class A
{
private:
static int k;
int a =20;
public:
class B
{
public:
void fun(const A& b)
{
cout << k << endl; //这里可以直接访问;
cout <<b.a << endl; //这里就不能直接访问,需要使用类名调用;
}
};
};
int A::k = 10;
int main()
{
A::B b;
b.fun(A());
return 0;
}
总结一下—》特性:
- 内部类可以定义在外部类的public、protected、private都是可以的。
- 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。
- sizeof(外部类)=外部类,和内部类没有任何关系。
4 再次理解封装
C++是基于面向对象的程序,面向对象有三大特性即:封装、继承、多态。
C++通过类,将一个对象的属性与行为结合在一起,使其更符合人们对于一件事物的认知**,将属于该对象的所有东西打包在一起;通过访问限定符选择性的将其部分功能开放出来与其他对象进行交互,**而对于对象内部的一些实现细节,外部用户不需要知道,知道了有些情况下也没用,反而增加了使用或者维护的难度,让整个事情复杂化