类的定义
关键字class
class Classname
{
//类体:由成员函数和成员变量组成
};//一定要注意后面的分号
类定义的两种方式:
1.声明和定义全部放在类体中,需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
2.声明放在.h文件中,类的定义放在.cpp文件中。
类的访问限定符及封装
访问限定符 public(公有) private(私有) protected(保护)
说明:
1.public修饰的成员在类外可以直接被访问。
2.protected和private修饰的成员在类外不能被直接访问(此处protected和private是类似的)。
3.访问权限 作用域从该访问限定符出现的位置开始到下一个访问限定符出现为止。
4.class的默认访问权限为private,struct为public。
注意,访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
类的作用域 ::作用域解析符
class Person
{
public:
void PrintPersonInfo();
private:
char name[20];
int age;
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo(){}
如何计算类的大小?
//既有成员变量,又有成员函数
class A1
{
public:
void f1(){}
private:
int a;
};
//只有成员函数
class A2
{
public:
void f2(){}
};
//空类
class A3
{};
//sizeof(A1)=4
//sizeof(A2)=1
//sizeof(A3)=1
一个类的大小,实际就是该类中的成员变量之和,当然也要进行内存对齐。
空类比较特殊,编译器给了一个字节来标识这个类。
this指针
C++编译器给每个“成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。
只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
指针特性
1.this指针类型:类类型* const。
2.只能在成员函数的内部使用。
3.this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4.this指针是成员函数的第一个隐含的指针形参,一般情况下通过ecx寄存器自动传递,不需要用户传递。
类的成员函数
构造函数
构造函数是一个特殊的成员函数,名字与类名相同,创建类型时由编译器自动调用保证每个数据成员都有一个合适的初值,并且在对象的生命周期内只调用一次并不是开空间创建对象,而是初始化对象。
特性
1.函数名与类名相同。
2.无返回值。
3.对象实例化时编译器自动调用对应的构造函数。
4.构造函数可以重载。
5.如果类中没有显示定义构造函数,则C++编译器自动生成一个默认构造函数,一旦显示定义编译器将不再生成。
6.无参的构造函数和全缺省的构造函数都称为默认构造函数。
class Date
{
public:
//无参构造函数
Date(){}
//带参构造函数(函数体中的语句只能将其称作为赋值,而不能被称作初始化。初始化只初始化一次,而构造体内可以多次赋值)
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//初始化列表:以一个:为开始,以,分隔成员列表,每个‘成员变量’后面放一个括号的表达式或者初始值
Date(int year, int month, int day)
:_year(_year)
, _month(month)
, _day(day)
{}
//类中包含1.引用成员变量,const成员变量,类类型成员(该类没有构造函数)
//尽量使用初始化列表初始化,对于自定义类型成员变量,一定会先使用初始化列表初始化
//成员变量的声明次序就是初始化列表的初始化顺序,与初始化列表的先后次序无关
private:
int _year;
int _month;
int _day;
};
void Test()
{
Date d1();//调用无参构造函数
Date d2(2000, 10, 1);//调用带参构造函数
//如果通过无参构造函数创建对象时,对象后面不用跟括号否则成了函数声明
Date d3();//声明d3函数,该函数无参,返回一个Date对象
}
析构函数
不是完成对象的销毁,局部对象的销毁工作是由编译器完成的。
对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。
特性
1.析构函数名实在类名前加上字符~。
2.无参数无返回值。
3.一个类有且只有一个析构函数。若未显示定义,系统会自动生成默认的析构函数。
4.对象生命周期结束时,C++编译系统自动调用析构函数。
拷贝构造
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
特性
- 拷贝构造函数是构造函数的一个重载形式。
- 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
3.若未显示定义,系统生成默认的拷贝构造函数(对于某些是一种浅拷贝)。
运算符重载
C++为了增强代码的可读性引入了运算符重载。
函数名字为:关键字operator 重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
特性
- 不能通过连接其他符号来创建新的操作符:比如operator@。
- .重载操作符必须有一个类类型或者枚举类型的操作数。
- 用于内置类型的操作符,其含义不能改变,例如:内置的整型 + ,不 能改变其含义。
- 作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的。
- 操作符有一个默认的形参this,限定为第一个形参。
- 不能重载的运算符:.* (成员指针访问运算符)::(域运算符)sizeof (长度运算符)? : (条件运算符)
const 成员
在成员函数后面加const
1.const修饰类的成员函数 称为const成员函数 。
实际修饰该成员函数this指针 表明该类的成员函数不能对类的任何成员进行修改。
- const对象可以调用其他的const函数。
- 非const对象可以调用非const成员函数和const成员函数。
- const成员函数内可以调用其他的const 成员函数。
- 非const成员函数内可以调用其他的const成员函数和非const成员函数
static成员
静态的成员变量一定要在类外进行初始化
特性
- 静态成员为所有类对象所共享,不属于某个具体的实例。
- 静态成员变量必须在类外定义,定义时不添加static关键字。
- 类静态成员即可用类名::静态成员 或者 对象.静态成员来访问。
- 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。
- 静态成员和类的普通成员一样,也有public、protected、private 3种访问级别,也可以具有返回值,const修饰符等参数。
友元
友元函数 :
友元函数可以直接访问类的私有成员 定义在类外的普通函数,但要在类内声明 前面加上 friend关键字
- 友元函数可访问类的私有成员,但不是类的成员函数 。
- 友元函数不能用const修饰 。
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限制 。
- 一个函数可以是多个类的友元函数 友元函数的调用与普通函数的调用和原理相同。
友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以防问另一个类中的非公有成员
- 友元关系是单向的,不具有交换性
- 友元关系不能传递
内部类 就是外部类的友元类
特性:
- 内部类可以定义在外部类的public、protected、private都是可以的。
- 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象 / 类名。
- sizeof(外部类) = 外部类,和内部类没有任何关系。