面向对象编程
面向过程(Procedure Oriented简称PO)
当解决一个问题的时候,面向过程会把事情拆分成:一个个函数和数据。然后按照定的顺序,执行完这些方法,事情就搞定了
面向对象(Object Oriented简称OO)
当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决
下面举个例子带你了解面向过程和面向对象的区别
有脏衣服需要清洗,怎么洗干净?
面向过程:
面向对象:
类与对象:
类:对某一事物的抽象
对象:某一类事物的个体,具体且唯一
class
类
在c++语言中是一种数据类型,用于描述某一个类的事物,包括属性与方法(函数)
定义:
示例:
对象
具体化某一个事物,成为一个具体的个体,创建对象后才会分配内存空间
创建方式:
<类名><对象名>;
<类名>*<对象指针名>=new<类名>();
访问属性与方法
<对象名>.<属性或方法>;
<对象指针名>-><属性或方法>;
访问权限
class默认权限是private
public 共有的 :一个类的public成员变量、成员函数,可以通过类的成员函数、类的实例变量进行 访问
private 私有的:一个类的private成员变量、成员函数,无法通过类的实例变量进行访问。但是可 以通过类的友元函数、友元类进行访问。
protected 受保护的:一个类的protected成员变量、成员函数,无法通过类的实—例变量进行访 问。但是可以通过类的友元函数、友元类进行访问。
构造函数
在构造对象时自动调用此函数,往往用来初始化对象内的成员变量
定义:函数名与类名一致且没有返回值
默认构造函数
当类中没有构造函数时,编译器会自动生成一个构造函数。
构造函数的重载
针对不同的初始化方式,可以重载构造函数
初始化列表
在初始化时,也可以使用初始化列表的方式来实现构造函数,一般用在继承中
拷贝构造函数
当一个对象需要通过另一个对象初始化,则需要使用拷贝构造函数
什么时间会调用拷贝构造函数?
主动创建对象时,用一个对象去初始化另一个对象的时候
一个对象以值传递的形式传入函数体
一个对象以值的形式从函数返回
C++标准允许一种(编译器)实现省略创建一个只是为了初始化另一个同类型对象的临时对 象。指定这个参数(-fno-elide-constructors)将关闭这种优化
深拷贝与浅拷贝
浅拷贝:默认的拷贝构造函数为浅拷贝,针对指针对象,只拷贝指针存储的地址
深拷贝:针对指针对象,拷贝指针指向的空间
explicit
explicit关键字只能用来修饰类的构造函数,且最好只修饰只有一个参数的构造函数,被修饰的构造函数不能发生相应的隐式类型转换,只能以显示的方式进行类型转换
何时触发隐式拷贝构造函数?
1.一个对象作为函数参数,以值传递的方式传入函数体
2.一个对象作为函数返回值,以值传递的方式从函数返回
3.以A a = b的方式构造a,其中b也是A类型
析构函数
在销毁对象时自动调用此函数,往往用来释放对象内申请的资源
定义:
与类名相同,在前面加位取反符~。且不能有任何参数与返回值
特点:没有参数没有返回值,但有this指针,析构函数不能用const修饰,一个类有且只有一个析构函数,所以肯定不能重载
static关键字
static表示静态关键字,可以用于修饰成员变量与成员函数
静态成员可以通过双冒号来使用,即<类名><静态成员名>
修饰成员变量
语法:在class中进行声明—— static<类型修饰符><变量名>
在class外进行初始化——<类型修饰符><类名>:<变量名>=<初始化值>
特点:static修饰的成员变量属于类不属于具体的对象
static成员变量的内存在程序开始运行时分配,程序运行结束时释放内存
static成员变量对于所有的对象是共享的,并在对象创建之前就已经产生了
静态成员使用前必须初始化,否则会在linker(链接)步骤时出错
在成员函数中可以正常访问静态成员变量
修饰成员函数
语法:static<函数返回值><函数名>(参数列表)
特点:可以被对象直接使用
可以通过类名直接访问
不能使用this指针,与类关联,不与对象关联,在调用静态函数时,可以在没有对象时调用
不能访问清静态成员,只能访问静态成员
何时使用static:一切不需要实例化(创建对象)就可以有确定行为方式的函数都应该设计成静态的。
this指针
用于保存对象的地址,每一个非静态函数中都有一个隐藏参数this
常见使用方式:在非静态函数中,需要返回对象本身
在非静态函数中,传入形参名与对象内成员变量相同时区分两个变量
const关键字
const成员变量
const成员变量只能在初始化列表中初始化
const成员函数
防止成员函数修改非静态成员变量的值,const成员函数可以修改静态成员变量,const成员函数也可以与同名非const成员函数构成函数重载。
友元
友元函数
友元函数不是成员函数,它定义在类的外部,只需要在类中声明即可,友元函数可以访问所有私有成员和保护成员,一般情况下不去使用,使用不当会破坏程序面向对象的特性。
语法:friend<函数声明>
友元类
一个类声明另一个类是自己的友元,假如类A声明类B是自己的友元,那么在类B中可以访问类A所有的私有成员和保护成员。
语法:friend<类名>
注意:友元不具有相互性,友元不能被继承,友元不具有传递性。
运算符重载
C++语言预定义的运算符只能操作基础数据类型,对于用户自定义的类型,在进行运算时也需要类似的操作,运算符重载实际上是对运算符赋予新的运算方式,使对象的运算操作更加简洁明了。
大部分运算符可以重载,少部分不行
重载运算符可以对运算符号做出新的解释,但基本语义不变,无法改变运算符优先级,无法改变运算符结构性,无法改变运算符所需要的操作数,无法创建新的运算符。
语法:
类的成员函数:<函数返回值> operator<运算符>(<形参表>) { <函数体> }
类的友元函数:friend<函数返回值> operator <运算符>(<形参表>){ <函数体> }
内联函数
引入内联函数的目的是为了解决程序中函数调用的效率问题。
原理:内联函数在编译器阶段是直接复制"镶嵌"到主函数中去的,就是将内联函数的代码直接放在 内联函数的位置上,这与一般函数不同,主函数在调用一般函数的时候,是指令跳转到被 调用函数的入口地址,执行完被调用函数后,指令再跳转回主函数上继续执行后面的代码; 而由于内联函数是将函数的代码直接放在了函数的位置上,所以没有指令跳转,指令按顺 序执行。
语法:函数声明和定义必须在同一文件进行,声明与定义时需要添加inline修饰符
inline<返回值><函数名>(<形参表>){<函数体>}
内联函数内不允许使用循环语句与开关语句
内联函数不能超过10行,如果超过则编译器不会替换,而还是使用调用的方式调用函数
类与内联函数:类内定义的函数都是内敛函数,不管是否有inline修饰符,声明在类内,定义在类 外,看是否有inline修饰符。
与宏定义的区别:宏是由预处理器进行代码替换,而内联函数由编译器进行代码替换内联函数是 真正的函数。