文章目录
- 再谈构造函数
- 初始化列表
- static
- 概念:
- 友元
- 友元函数
- 友元类
- 内部类
- 再次理解类和对象
再谈构造函数
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
上述代码有了初始值,但是不是初始化,因为初始化是一次性的,而构造函数可以多次赋值
初始化列表
🚩初始化列表:以一个 : 开始,接着以 ,分隔数据列表,每个对象后面接包含初始值的括号
class Date
{
public:Date(int year, int month, int day):_year(year),_month(month),_day(day){}
private:int _year;int _month;int _day;
};
1,成员对象在初始化列表只能出现一次,
2,类中包含以下情况必须用初始化列表初始化
1,const 修饰
2, 引用
3,自定义类型(无默认构造函数的)
class A
{
public:A(int a):_a(a){ }
private:int _a;
};
class B
{
public:B(int b, int ret,int obj):_b(b), _ret(ret), _obj(obj){}
private:const int _b;int& _ret;A _obj;
};
🚩 3,尽量使用列表初始化,因为无论是否使用列表初始化,自定义类型都会先进行列表初始化。
🚩 4,成员变量的声明次序就是初始化列表的初始化顺序,与初始化的列表顺序无关,
试问以下代码输出什么?
#include <iostream>
using namespace std;
class A
{
public:A(int a):_a1(a), _a2(_a1){}void print(){cout << _a1 << " " << _a2;}
private:int _a2;int _a1;
};int main()
{A aa(1);aa.print();return 0;
}
1 随机值
因为声明顺序先_a2,再a1。 初始化时_a1随机值赋给了_a2,而_a1得到1,
static
概念:
声明static的类成员叫静态成员,用static修饰的成员变量叫静态成员变量,用static修饰的成员函数叫静态成员函数,静态成员变量一定要在类外初始化
#include <iostream>
using namespace std;
class A
{
public:A(){_scount++;}A(const A& a){_scount++;}static int Getscount(){return _scount;}~A(){--_scount;}
private:static int _scount;
};int A::_scount = 0;int main()
{cout << A::Getscount() << endl;A a1, a2;A a3(a1);cout << A::Getscount() << endl;return 0;
}
0
3
🚩1,静态成员为所有类对象所共享,不属于某个具体的类对象,存在静态区,所有对象都能调用
2,静态成员变量必须在类外定义,定义时不需要static,类中只是声明
3,静态成员可以用类名::加静态成员访问,也可以类对象.加静态成员访问,
4,静态成员函数没有this指针,不能访问任何非静态成员,
5,类中的静态成员也受到public,private限制
问题:
1,静态成员函数可以调用非静态成员函数吗?
不可以,无this指针,非静态成员函数必须通过类对象调用(因为可能访问对象的成员变量)
2,非静态成员函数可以调用静态成员函数吗?
可以,静态成员函数全局共享,都可以用,
友元
友元提供了一种突破封装的模式,提供了便利,但使用友元会增加耦合度,所有友元不宜多用,
友元分为:友元函数,友元类,
友元函数
#include <iostream>
using namespace std;
class A
{
public:A(int hour = 10, int minute = 30):_hour(hour),_minute(minute){}ostream& operator<<(ostream& _cout){_cout << _hour <<'-'<< _minute << endl;return _cout;}
private:int _hour;int _minute;
};
int main()
{A a1,a2;a1 << cout; return 0;
}
a1<<cout -> a1.operator<<(&a1,cout)
不符合常规调用,
但是有this指针,所以又不能反过来调用,因为cout<<a1,this指针会和cout抢位置,
🚩实际应用中,cout要在第一个形参位置,所以要将operator重载为全局函数,但是全局函数又访问不了私有成员,所以我们用到友元
🚩友元函数是定义在类外部的普通函数,可以直接访问类的私有成员,不属于任何类,但是要在类内部声明,声明时前面加friend,
#include <iostream>
using namespace std;
class A
{friend ostream& operator<<(ostream& _cout, const A& a);friend istream& operator>>(istream& _cin, A& a);
public:A(int hour=10,int minute=40):_hour(hour), _minute(minute){ }private:int _hour;int _minute;
};
ostream& operator<<(ostream& _cout, const A& a)
{_cout << a._hour <<"-" << a._minute << endl;return _cout;
}
istream& operator>>(istream& _cin, A& a)
{_cin >> a._hour >> a._minute;return _cin;
}
int main()
{A a1, a2;cin >> a2;//14 20cout << a1 << a2;return 0;
}
14-20
10-40
说明:
1,友元函数可以直接访问类的私有和保护成员,但不是类的成员函数,
2,友元函数不能被const修饰,
3,友元可以定义在类的任何位置,不受访问限定符限制
4,一个函数可以被多个类友元,
5,友元函数和普通函数调用相同,
友元类
🚩 1,A类是B类的友元,则A可以访问所有B的私有成员变量,但反过来不行。
🚩 2,友元无传递性,A类是B类的友元,B是C的友元,但A不能访问C类的私有变量,
class Time
{friend class Date;
public:
private:int _hour;int _minute;
};class Date
{
public:void settime(int hour, int minute){_t._hour = hour;_t._minute = minute;}
private:int _year;int _month;int _day;Time _t;
};
内部类
:一个类如果定义在另一个类的里面,就叫内部类,内部类属于独立的类,它不属于外部的类,更不能通过外部类访问内部类的成员变量,外部类对内部类没有任何优越权限
注意:
内部类就是外部类的友元,但外部类不是内部的友元
特性
1,内部类可以定义在外部类任何位置,不受访问限定符限定
2,内部类可以直接访问外部的static成员,不需要加类名和.
3,sizeof(外部类)=外部类,和内部类无关
#include <iostream>
using namespace std;
class A
{
public:class B{public:void test(const A& a){cout << k << endl;cout << a.h << endl;}private:};
private:static int k;int h=2;
};
int A::k = 3;
int main()
{A::B t;t.test(A());//隐式对象return 0;
}
再次理解类和对象
总结:类是对某一类实体对象进行描述的,描述对象的各种属性,描述完成后就形成一种新的自定义类型,再通过自定义类型实例化具体对象