C++基础(二)
1.类和对象
1.1类的定义类的定义格式
class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意定义结束时后面分号不省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或成员函数。
C++一种实现封装的方式,用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用
public(公有)修饰的成员在类外可以直接被访问,protected(保护)和private(私有)修饰的成员在类外不能直接被访问,protected和private是一样的访问权限作用域从该访问权限出现的位置开始直到下一个访问限定符出现为止,如果后面没有访问限定符,作用域就到 } 即类结束额外注意:
class定义成员没有被访问限定符修饰时默认为private,struct默认为public一般成员变量都会被限制为private/protected,需要给别人使用的成员函数会被放为public 1.3类域类定义了一个新的作用域,类所有成员都在类的作用域中,在类体外定义成员时,需要使用 ::作用域操作符指明成员属于哪个类域
类域影响的是编译的查找规则,下面程序中Init如果不指定类域Stack,那么编译器就会把Init当成全局函数,那么编译时找不到_top等成员,就会到类域去找
注意:
类里面的函数声明定义分离,类创建后形成了新的类域,需要指定类域,否则不可访问2.实例化
2.1实例化概念 用类型在物理内存中创建的过程,称为类实例化出对象类是对象进行一种抽象描述,是一个模型一样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,用类实例化出对象时,才会去分配空间内存对齐规则
第一个成员在与结构体偏移量为0处的地址处其他成员变量要对齐对齐数的整数倍的地址处对齐数=编译器默认的对齐数与该成员的大小的较小值VS x64平台默认对齐数是4,x86默认对齐数是8结构体总大小为:最大对齐数(所有类型变量最大者与默认对齐数取最小)的整数倍如果嵌套了结构体的情况,嵌套的结构体对齐到自己最大对齐数的整数倍,结构体整体大小就是所有最大对齐数(含嵌套结构体对齐数)的整数倍3.this指针
编译器编译后,类的成员函数默认都会在形参第一个位置,增加一个当前类的指针,叫做this指针
例如Date类中的Init原型为 void Init(Date * const this,int year ,int month,int day),类的成员函数中访问成员变量,本质是通过this指针访问的,如Init函数中给_year赋值,this->_year=year
原型:
真实原型
C++规定不准在实参和形参的位置写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针,this指针不能修改,但this指针指向的内容可以
this指针存在栈里
4.类的默认成员函数
默认成员函数就是用户没有显示定义,编译器会自动生成的成员函数称为默认成员函数
4.1构造函数构造函数是特殊的成员函数,需要注意的是,构造函数虽然名字叫构造函数,但是构造函数的主要内容并不是开辟空间创造对象(我们平常使用的局部对象是栈帧创建时,空间就开好了),而是对象实例化时初始化对象。构造函数的本质是要替代我们以前Stack和Date类中写的Init函数的功能,构造函数自动调用的特点就完美替代了Init
构造函数的特点:
函数名与类名相同无返回值(返回值啥也不需要给,也不要写void C++就是这样规定)对象实例化时系统会自动调用对应的构造函数构造函数可以重载如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显示定义编译器将不再生成无参构造函数,全缺省构造函数,我们不写构造时编译器默认生成的构造函数,都叫做默认构造函数。但是这三个有且只能有一个存在,不能同时存在。无参构造函数和全缺省构造函数虽然构成函数重载,但是调用时会存在歧义。注意并不是只有默认构造函数就是编译器默认生成的那就是构造函数,无参构造函数,全缺省构造函数也是默认构造函数,总结一下就是不传参就能调用
我们不写,编译器默认生成的构造,对内置类型成员变量的初始化没有要求,也就是说是是否初始化是不确定的,看编译器。
C++把类型分为自定义类型和内置类型(基本类型)。内置类型就是语言提供的原生数据类型,如int/char/double/指针等,自定义类型就是我们使用class/struct等关键字自己定义的类型。这里构造函数自动初始化,VS也将内置类型size初始化了,不同的编译器初始化值不同,C++并没有规定
对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化。如果这个成员变量,没有默认的构造函数,那么就会报错,我们要初始化这个成员变量,需要用初始化列表才能解决
总结:大多数情况下,构造函数都需要我们自己去实现,少数情况类似MyQueue且Stack有默认构造函数时,MyQueue自动生成就可以用
4.2析构函数析构函数的特点:
1.析构函数名是在类名前面加上字符~
2.无参无返回值(与构造函数一致)
3.一个类只能有一个析构函数。若未显示定义,系统也会自动生成默认的析构函数
4.对象声明周期结束时,系统会自动调用析构函数,
5.跟构造函数类似,我们不写编译器自动生成的析构函数对内置类型成员不做处理,自定义类型成员会调用其他的析构函数
6.还需注意的是我们显示析构函数,对于自定义类型成员也会调用他的析构函数,也就是说自定义类型成员无论什么情况都会自动调用析构函数。
MyQueue里的析构啥也没干,但是C++规定会调用其他的析构来释放内存
如果没有申请资源时,析构可以不写,直接使用编译器生成的默认析构函数,如Date,如果默认生成的析构可以用,也就不需要显示写析构如MyQueue,但是有资源申请时,一定要直接写析构,否则会造成资源泄漏如Stack
4.5运算符重载 当运算符被用于类型的对象时,C++语言允许我们通过运算符重载的形式指定新的含义。C++规定类类型对象使用运算符时,必须转换成调用对应运算符重载,若没有则编译器报错运算符重载是具有特定名字的函数,他的名字是由operator和后面要定义的运算符共同构成。和其他函数一样,它也具有其返回类型和参数列表以及函数体Ongwu博客 版权声明:以上内容未经允许不得转载!授权事宜或对内容有异议或投诉,请联系站长,将尽快回复您,谢谢合作!