概述
文章目录
- 1、面向对象和面向过程的区别
- 2、封装
- 3、this指针
- 4、构造函数
- 5、析构函数
- 6、拷贝构造函数
- 7、运算符重载
- 8、const关键字
- 9、static
- 10、类和对象的区分
1、面向对象和面向过程的区别
1.1、面向对象和面向过程的区别
面向过程:是以函数驱动的,通过函数之间的相互调用次序来完成事情,重视完成该件事的步骤。
面向对象:关注的不再是完成事情的步骤,关心:如何通过对象之间的交互将事情完成。
1.2、C++和C语言的区别:
- 面向对象和面向过程;
- C++编译器对语法的检测更加严格;
- C++语言更加的人性化;
- C++支持面向对象:封装、继承、多态;
- C++独有的STL;
- C++更适合做比较复杂、大的工程。
2、封装
2.1、什么是封装:将数据和操作数据的方法进行有机的结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
2.2、C++是如何实现封装特性的?
class:通过类可以将数据和操作数据的方法进行有机结合;
访问限定符:限定类中的成员能否直接在类外被使用。(private、protected、public)
注意:class的默认访问权限是private;struct为public(因为struct要兼容C)
2.3、如何求一个类的大小?
与求结构体大小相同的,即:将非静态成员变量相加+内存对齐。 与类中的构造函数、析构函数、拷贝构造函数、赋值运算符重载、取地址运算、const取地址运算无关。
空类的大小为1。
3、this指针
3.1、为什么需要this指针?
C++编译器给每个“非静态的成员函数”增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户时透明的,即用户不需要来传递,编译器自动完成。
3.2 、什么是this指针?
在C++中,每一个对象都能通过this指针来访问自己的地址。this指针是所有成员函数的隐含参数。因此,在成员函数内部,可以用来指向调用对象。
3.3、this指针的特性
- this指针的类型:类类型 T* const
- 作用域:只能在类“非静态成员函数”中使用
- this指针本质上是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针
- this指针是成员函数中第一个隐含的指针形参,一般情况下由编译器通过ecx寄存器自动传递,不需要用户传递。
3.4、this指针能否为空?
对象.成员函数();this指针一定不为空
指针->成员函数();this指针可能为空
如果this指针是空的,当在成员函数中未使用任何非静态成员变量时,则代码不会崩溃,否则代码就会崩溃。
3.5、this指针存储在哪里?
其实编译器在生成程序时加入了获取对象首地址的相关代码。并把获取的首地址存放在了寄存器ECX中(VC++编译器是放在ECX中,其它编译器有可能不同)。也就是成员函数的其它参数正常都是存放在栈中。而this指针参数则是存放在寄存器中。
this指针会因编译器不同,而放置的位置不同。可能是栈,也可能是寄存器,甚至全局变量。
4、构造函数
4.1、概念:构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。
注意:构造函数不负责给对象开辟空间,只完成对对象中成员变量的初始化工作。
4.2、特性:
- 名字必须与类名相同;
- 没有返回值类型;
- 在创建对象时,由编译器自动进行调用,并且在整个对象的声明周期内只调用一次;
- 构造可以重载;
- 具有初始化列表;
- 如果用户没有显式给出构造函数,则编译器会生成一份无参的构造函数,但如果用户显式给出了任何构造函数,则编译器不再生成;
- 无参构造函数和全缺省构造函数都称为默认的构造函数,并且他们不能共存。
初始化列表
1、以下几种情况必须使用初始化列表:
a、常量成员,因为常量只能初始化不能赋值,所以必须放到初始化列表里面;
b、引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以必须放到初始化列表里面;
c、类类型对象且该类具有带有参数构造函数时必须在构造函数初始化列表的位置进行初始化。
2、注意:
a、初始化列表用户可以不用显式给出,但是不给出不代表没有初始化列表,编译器会自动补全,只不过在不全时给成员变量中放置的是随机值。
b、成员的初始化次序:并不是按照其在初始化列表中出现的先后次序来进行初始化,而是与成员变量在类中的声明先后次序有关。因此:尽量避免使用成员初始化成员。
4.3、构造函数不能使用const修饰
const修饰成员函数,本质在修饰this指针,表明:this指针指向的对象中的内容是不能被修改的。
有些成员变量需要经过大量运算然后在构造函数体中进行赋值,如果构造函数可以被const修饰,则在构造函数中就不能对成员变量进行修改了!!
4.4、构造函数不能是静态的成员函数
原因:构造函数主要是针对非静态成员变量进行初始化,而静态成员函数一般只能直接操作静态成员变量,如果构造函数可以被static修饰,则构造函数就不能对非静态的成员变量进行初始化,违背了构造函数的意义。
构造函数调用场景:当用户在创建对象时,编译器会自动调用构造函数,对对象中的成员变量进行初始化。
4.5、默认构造函数
如果用户没有在类中显式定义任何构造函数的情况下,则编译器会给该类生成一份无参的默认构造函数。
什么情况下编译器会生成默认的成员函数(vs下):
- 类和对象阶段:类A中如果包含类B的对象,并且类A没有显式定义任何构造函数,而类B显式定义了无参或者全缺省的构造函数。编译器一定会给类A生成一份默认的无参构造函数。----编译器要在给A类生成的无参构造函数初始化列表位置调用B类的构造函数,完成B类中成员变量的初始化。
- 继承位置
- 虚拟继承下
- 类中带有虚函数
5、析构函数
5.1、概念:与构造函数功能相反,在对象销毁时,由编译器自动调用,完成对象中资源的清理工作。注意:不负责回收对象的空间,只负责将对象空间中的资源清理干净。
局部对象:空间在栈上,当函数运行结束后,栈帧被系统回收,对象的空间则被回收了。
堆上对象:delete p,最终对象的空间是由operator delete(void*)—>free
5.2、特性
- 名字是在构造函数名字前加~
- 没有返回值类型
- 没有参数,即:析构函数不能重载,一个类最多只能有一个析构函数
- 在对象销毁时,由编译器自动调用,完成对象中资源的清理工作
- 语法:用户没有显式实现时,则编译器会生成一份默认的析构函数
- 注意:类中如果没有涉及到资源管理时,析构函数是否给出无所谓;类中涉及到资源管理时,用户必须要显式给出析构函数,在析构函数中清理对象的资源。
调用场景:当对象被销毁时,由编译器自动调用,完成对象中资源的清理工作。
6、拷贝构造函数
6.1、概念:只有单个形参,该形参是对本类 类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
6.2、特性拷贝构造函数是一种特殊的构造函数,因此构造函数的特性,拷贝构造函数有些也满足。
- 拷贝构造函数可以看成是构造函数的一种重载形式
- 参数:必须是类类型对象的引用,否则:编译报错,因为如果是传值,会造成无限递归
6.4、编译器生成的默认拷贝构造函数:
(vs下)对于一般的类,编译器并没有给其真正生成一份拷贝构造函数,但是发现:编译器完成了拷贝的工作。
当类A中由类B的对象时,并且类B显式给出了其拷贝构造函数,则编译器会给类A生成一份默认拷贝构造函数。
默认的拷贝构造函数对象的内存存储按照字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。
注意:
如果类中未涉及到资源管理时,用户是否显式提供拷贝构造都可;
如果类中涉及到资源管理时,用户必须要显式提供拷贝构造函数。
因为:编译器默认的拷贝方式是将一个对象中的内容原封不动的拷贝到另外一个对象中(浅拷贝),最后就会导致多个对象共享同一份资源,当对象在销毁时候,会导致一份资源被释放多次而引起代码崩溃。
6.5、调用场景
当使用已经存在的对象创建新对象时,则调用拷贝构造函数。
Date d1(2008,08,08);
Date d2(d1);
Date d2 = d1;
1、以值的方式传递类类型的参数;
2、以值的方式返回(类类型),编译器可能会优化。
7、运算符重载
7.1、概念:C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数类型与普通的函数相似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator 操作符(参数列表)
7.2、运算符重载注意事项:
- 不能臆造一个运算符:operator @
- 不能被重载的运算符只有5个, 点号. 三目运算?: 作用域访问符:: 运算符sizeof 以及.*
- 如果该运算符重载为类的成员函数时,其形参个数少一个,因为有隐藏的this
- 前置++/后置++
//前置++
Date& operator++(){
_day += 1;
return *this;
}
//后置++
Date operator++(int){
//注意:
//1、实际后置++函数有两个参数;
//2、但是在调用时,int类型的参数不用传递;
//3、前置++比后置++效率高
Date temp(*this);
_day += 1;
return temp;
}
//语法上:为了让前置++和后置++形成重载,在设计时就给后置++多增加了一个int类型的参数
8、const关键字
C语言:const只能修饰变量,表明该变量中的内容不能修改,因此在定义被const修饰的变量时,需要给出该变量的初始值。
;C++:
- const变量:表明该变量已经是一个常量了,而且具有宏替换的属性,编译器在编译阶段,会将常量替换为其对应的常量值。
因此:在C++中建议尽量使用const定义的常量来取代宏常量。 - const类成员变量:该成员变量必须要在构造函数初始化列表的位置进行初始化。即:如果类中包含有const修饰的成员变量,则该类必须显式提供构造函数。
- const类成员函数:
const修饰类成员函数,实际修饰的时隐藏的this指针;
const不能修改静态成员函数
const成员函数中不能修改任何非静态成员变量,除非:mutable。也不能调用任何非const成员。
9、static
C语言:
- 修饰变量:
局部变量:改变了变量的生命周期,使得静态局部变量出了作用域依然存在,直到程序结束;
全局变量:使得只能在本源文件中使用。 - 函数:只能在本源文件中使用。
C++:
- 变量:全局变量、局部变量---->与C语言中的相同;
静态成员变量 和 普通成员变量 的区别:
【静态成员变量】 | 【普通成员变量】 |
---|---|
是类的属性,没有包含在对象中(所有对象共享) | 属于对象的,包含在对象中 |
不会影响sizeof结果 | sizeof算普通成员变量 |
不能在构造函数初始化列表进行初始化,必须在类外单独进行初始化 | 必须在初始化列表进行初始化 |
访问形式: 类型::静态成员变量 / 对象.静态成员变量 | 访问方式:只能通过对象.普通成员变量 |
既可以在普通成员函数也可以在静态成员函数中访问 | 只能在普通成员函数中访问 |
- 函数:普通函数---->与C语言中的相同
静态成员函数 和 普通成员函数 的区别:
【静态成员函数】 | 【普通成员函数】 |
---|---|
没有this指针 | 具有隐藏的this指针 |
访问方式:类名:: / 对象.成员函数 | 访问方式:对象.普通成员函数 |
内部只能访问静态成员变量 | 静态和普通成员变量都可以访问 |
不能被const修饰 | 可以被const修饰 |
不能是虚函数 | 可以是虚函数 |
不能调用普通的成员函数 | 可以调用静态成员函数 |
10、类和对象的区分
【类】 | 【对象】 |
---|---|
用来描述对象的,说明对象有哪些属性,有哪些功能 | 是类具体产生的实体 |
也是一个自定义的类型 | 是真真正正存在的 |
是一种新的作用域 | 是类类型创建出来的变量---->对象 |
里面不能存储数据的,类相当于一张图纸 | 对象中才真正存储数据---->房子 |
最后
以上就是英俊刺猬为你收集整理的C++_类和对象的全部内容,希望文章能够帮你解决C++_类和对象所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复