1:类和对象的基础知识,如类的定义,访问限定符,面向对象封装性,对象的大小计算等等。
类的定义:类其实是一种由用户定义的特殊的(类型中包含了对数据操作的函数)数据类型,它是将不同类型的数据和这些数据相关的操作封装在一起的集合体。
类的定义格式:
class<类名>
{
public:
<成员函数或数据成员的说明>
private:
<数据成员或成员函数的说明>
};
<各个成员函数的实现>
类的成员包括数据成员和成员函数两部分,类的成员又分为:共有的(public)、私有的(private)和保护的(protected)3类。
访问限定符(访问权限修饰符): public,private,protected。它们在类体内(即一对花括号内)出现的先后顺序无关,并且允许多次出现,用他们来说明类成员的访问权限。
注意:若没有访问限定符,默认该成员是私有的;类外只能访问共有的成员,不能访问私有的成员。
面向对象的封装性:封装性就是把对象的成员属性(数据)和成员方法(函数)结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含如下两个含义:
1>把对象的全部成员属性和全部成员方法结合在一起,形成一个不可分割的独立单位(即对象);
2>信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界,只保留有限的对外接口是指与外部发生联系。
例:
//创建一个学生类
class Student
{
//私有成员(数据),类外不能访问
private:
char*_name;
int _age;
char*_sex;
//共有成员函数,允许类外访问
public:
int Print(int x)
{
printf("%d ", x);
}
};
对象的大小计算:对象的大小为类中所有成员的大小之和(并且要遵循):
第一个成员在与结构体变量偏移量为0的地址处,其他成员要对齐到改成员的对齐数的整数倍的地址处,结构体的总大小为最大对其数的整数倍。
默认对其数:VS中为8,Linux中为4。
2:四个默认成员函数(构造函数、拷贝构造函数、析构函数和赋值运算符重载)及运算符重载相关知识
(1)构造函数:成员变量为私有的,要对其初始化必须用一个共有的成员函数来进行。且这个函数且在定义对象时自动执行一次,这个函数成为构造函数。
(2)拷贝构造函数:创建对象时使用同类对象来进行初始化,这时用的构造函数称为拷贝构造函数,拷贝构造函数是特殊的构造函数。
class Date
{
public:
//无参构造函数
Date()
{}
//带参的构造
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//缺省参数的构造函数
Date(int year = 2017, int month=1,int day=1)
{
_year = year;
_month = month;
_day = day;
}
//拷贝构造函数
Date(const Date&d)
{
_year = d._year;
_month = d._month;
_day = _day;
private:
int _year;
int _month;
int _day;
};
void test()
{
Date d1;
Date d2(2015, 1, 1);
Date d3();
}
void main()
{
test();
}
构造函数特征如下:
a.函数名与类名相同;
b.无返回值;
c.创建对象时系统会自动调用;
d.该函数可以重载;
e.构造函数可以在类里或者类外定义;
f.若类定义中没有给出构造函数,编译器会自动生成一个默认构造函数,若我们定义一个构造函数,系统不会自动生成默认构造函数;
g.无参构造函数和全缺省值的构造函数都认为是缺省构造函数,且缺省构造函数只能有一个。
拷贝构造函数特征如下:
a.拷贝构造函数本质上是一个构造函数的重载;
b.拷贝构造函数必须用引用传参数,用传值调用会引发无穷递归调用;
c.如果没有显示定义,系统会默认缺省的拷贝构造函数。缺省的拷贝构造函数会依次拷贝成员进行初始化。
(3)析构函数:当一个对象的生命周期结束后,c++编译系统会自动调用一个成员函数,即析构函数。
class Date
{
public:
//析构函数
~Date()
{}
private:
int _year;
int _month;
int _day;
};
析构函数特征如下:
a.析构函数名为(~<类名>);
b.析构函数无参数无返回值;
c.一个类只有一个析构函数。若为显示定义,系统会自动生成;
d.对象生命周期结束后,c++编译器会自动调用缺省的析构函数
e.析构函数体内并不是删除对象,而是做一些清理工作。
(4)赋值运算符的重载:拷贝构造函数是创建的对象,使用一个已有对象来初始化这个准备创建的对象。赋值运算符的重载是对一个已存在的对象进行拷贝赋值。
运算符重载的特征:
a.函数名为 operator+合法的运算符
b.运算符重载以后,不能改变运算符的优先级/结合性/操作数个数
例:
class Date
{
public:
//拷贝构造函数
Date()
{}
Date(const Date&d)
: _year(d._year)
, _month(d._month)
, _day(d._day)
{}
//赋值操作符的重载
Date&operator=(const Date&d)
{
if (this != 0)
{
this->_year = d._year;
this->_month = d._month;
this->_day = d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};
void test()
{
Date d1;
Date d2 = d1;//调用拷贝构造函数
Date d3;
d3 = d1;//调用赋值运算符的重载
}
3:隐含的this指针及对运算符重载背后做的事情。
this指针:每个成员函数(除构造函数)都有一个指针形参,它就是this指针。
特点:
a. this指针是隐式的。
b. 在调用成员函数的时候,编译器会将对象地址作为实参传递给this指针。
c. this指针始终是成员函数的第一个形参。
d. 不能在成员函数的形参中添加this指针的参数定义,也不能在调用时显示传递对象的地址给this指针。