1.类和对象的基础知识
类是对象的抽象,而对象是类的具体实例。类是一种抽象的数据类型,其定义为:class 类名{ };
类是创建对象的模板,代表了某一批对象的共性和特征。一个类可以创建多个对象,每个对象都是类类型的一个变量;创建对象的过程也叫类的实例化。每个对象都是类的一个具体实例,拥有类的成员变量和成员函数。与结构体一样,类只是一种复杂数据类型的声明,不占用内存空间。而对象是类型的一个变量,是通过类这种数据结构创建出来的一份实际存在的数据,所以占用内存。
//定义一个类类型
class Student
{
public: //访问限定符
//成员变量
char* _name;
int _age;
char _sex;
//成员函数
void Display()
{
cout<<"name:"<<_name<<endl;
cout<<"age:"<<_age<<endl;
cout<<"sex:"<<_sex<<endl;
}
};
class是C++新增加的一个关键字,专门用来定义类。Student是类的名称;{ }内部是类所包含的成员变量和成员函数,他们统称为类体。
类的实例化:
Student stu1;
注:在类定义的最后有一个分号,它是类定义的一部分,表示类定义结束。
2.访问限定符
public(公有):public成员在类外也可以直接访问。
protected(保护):protected成员在类外不能直接被访问。
private(私有):private成员在类外不能直接被访问。
class的默认访问权限是private。
3.面向对象的封装性
面向对象的四个基本特征为:抽象、封装、继承、多态。
抽象:表示同一类事物的本质。
封装:(1)封装是把有关的数据和操作代码封装在一个对象中,形成一个基本单位,各个对象之间相互独立,互不干扰。(2)是将对象中某些部分对外界隐藏,即隐蔽其内部细节,只留下少量接口,以便于与外界联系,接受外界的消息。这种队外界隐蔽的做法称为信息隐蔽,信息隐蔽还有利于数据安全,防止无关的人了解和修改数据。
继承:可以使用现有类的功能,在无需重新写原来类的情况下对这些功能进行扩展。通过继承创建出“子类”或者“派生类”,被继承的类叫做“基类”或者“父类”。
多态:由继承而产生的不同的派生类,其对象对同一消息会做出不同的响应,多态性增加了程序设计的灵活性。
4.对象大小计算
(1)C++中类的成员函数(放在代码段),静态存储的成员变量是不占类的大小的。
(2)空内的大小为一个字节。
(3)依然要遵循内存对齐原则。
5.四个默认成员函数
《1》构造函数
C++定义了一种特殊的初始化函数,叫做构造函数。当对象创建时,构造函数由系统自动调用一次。如下:
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year=1900,int month=1,int day=1)//构造函数
{
_year = year;
_month = month;
_day = day;
}
void Display()
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;//实例化出对象
d1.Display();
return 0;
}
我们看到,当对象d1创建时系统自动调用了构造函数。
【特征】:(1)函数名和类名相同
(2)无返回值
(3)构造对象时,系统自动调用。
(4)可以在类外/类内定义。
(5)当用户没有自己显示的定义构造函数时,系统会自动生成一个默认的构造函数。
(6)无参的构造函数和全缺省的构造函数都认为是都认为是缺省的构造函数,并且缺省的构造函数只能有一个。
《2》拷贝构造函数
拷贝构造函数是构造函数的重载,是有一个形参,而且形参是对本类类对象的引用(常用const修饰),这样的构造函数称为拷贝构造函数。拷贝构造函数是特殊的构造函数,创建对象时使用已经存在的同类对象来进行初始化,由编译器自动调用。如下:
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year=1900,int month=1,int day=1)//构造函数
{
_year = year;
_month = month;
_day = day;
cout<<"构造"<<endl;
}
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
cout<<"拷贝构造"<<endl;
}
void Display()
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;//实例化出对象,同时系统自动调用构造函数
d1.Display();
Date d2(d1);//系统自动调用拷贝构造函数
d2.Display();
return 0;
}
结果:
【特征】:(1)创建对象时使用同类对象进行初始化。
(2)必须使用引用传参,否则会出现无限递归。
(3)若没有显示定义,则系统会自动生成默认的拷贝构造函数。
《3》析构函数
析构函数与构造函数作用相反,是在对象被删除之前由系统自动调用析构函数执行清理工作。
如下:
【特征】:(1)在类名前加“~”。
(2)无参,无返回值,所以不能被重载,只有一个析构函数。
(3)若未显示定义,系统会自动生成默认的析构函数
(4)并不是删除对象,而是做一些清理工作。
《4》运算符重载
在C++中可以用关键字operator加上运算符来表示重载这个运算符。
也就是对已有的运算符重新进行定义,赋予另一种新的功能,以适应不同的数据类型。如下:
Date operator+(Date a,Date b)//两个日期相加
{
//
}
注意:不能重载的运算符!!!
域运算符
|
::
|
条件运算符
|
? :
|
成员访问运算符
|
.
|
指针运算符
|
*
|
长度运算符
|
sizeof
|
运算符重载规则:
1.C++除了上述的几个少数的运算符不能重载外,其他C++中已有的运算符都可以重载。
2.重载之后运算符的优先级不变。
3.运算符重载也不能改变原来运算符的操作数。
6.this指针
在每个成员函数中都包含一个特殊的指针,这个指针的名字是固定的,称为this。它是指向本类对象的指针,它的值是当前被调用的成员函数所在的对象的起始地址。this指针是隐式使用的,它是作为参数被传递给成员函数的。如下:
Date(const Date& d)
{
_year = d._year;//this->_year = d._year;
_month = d._month;//this->_month = d._month;
_day = d._day;//this->_day = d._day;
cout<<"拷贝构造"<<endl;
}
void Display()
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
//cout<<this->_year<<"-"<<this->_month<<"-"<<this->_day<<endl;
}
如上图后面的注释部分就是this指针所做的事情。
好啦,今天就更新到这儿啦!期待下一次见面。