c++是学习任何一门IT技术都必须要学的,在c++的学习重点和难点也就是类与封装了,在这里我这只老鸟总结出了一些类与封装基础,比较全面,对c++类与封装的入门学习必备。
一、如何定义类
定义一个类,本质上是定义一个数据类型的蓝图。这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。
class 类名
{
成员。。。。
};
访问限定符:
private: 私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
public: 公有成员在程序中类的外部是可访问的。可以不使用任何成员
函数来设置和获取公有变量的值
protected:保护成员变量或函数与私有成员十分相似,但有一点不
同,保护成员在派生类(即子类)中是可访问的。
什么是类的内部和类的外部?
在类的作用域范围内叫类的内部,在类的作用域访问外叫类的外部
注意:定义类的时候,类的成员函数可以在类的内部声明,在类的外部定义,在外部定义的时候需要加作用域。
在表示数据类型的时候,class可以省略,直接用类名表示数据类型。
class 和struct 有什么区别?
在不加访问限定符的情况下,class的成员默认是私有属性,struct 的成员默认是公有属性。
对象和类的关系:
类是某一事物的抽象,类是数据类型,对象是类的实例化,对象是变量名。
二、this指针
this指针默认在非静态的成员函数中存在。
指向当前对象的首地址,谁调用该成员函数,谁就是当前对象。this指针在表示成员变量的时候可以省略
三、构造函数
作用:初始化成员变量,初始化只会进行一次,所以任何一个对象只会
调用一次构造函数
特点:
1.函数名和类名一样
2.没有返回值
3.可以重载
4.如果没有自定义构造函数,编译器会提供默认的构造函数进行初始化工作
5.如果自定义构造函数,对象初始化不会调用默认的构造函数,而是调用自定义的构造函数
6.构造函数不需要主动调用,创建对象的时候会自动调用构造函数进行初始化
7.构造函数可以用初始化列表进行初始化
8.构造函数通常是公有的,如果是非公有将无法创建对象
默认构造函数无入参,无打印。
拷贝(复制)构造函数 copy construct function
作用:用一个已经存在的对象给新创建的对象初始化。有默认的拷贝构造函数,如果没有自定义,就用默认的。如果自定义拷贝构造函数,只会调用自定义的拷贝构造函数默认构造函数属于浅拷贝
深拷贝和浅拷贝
浅拷贝: 栈内存之间数据的拷贝
深拷贝: 堆内存之间数据的拷贝四、析构函数
作用:在对象生命周期结束的时候,回收对象的资源(内存)
特点:
1.函数名是类名前加~
2.没有返回值
3.没有入参,不能进行函数重载
4.如果没有自定义析构函数,编译器会提供默认的析构函数(默认析构函数无打印,且只会释放栈内存空间)
5.如果自定义析构函数,不会用默认的析构函数,只会用自定义的析构函数
6.析构函数不需要主动调用,在对象生命周期结束的时候自动调用
7.如果主动调用析构函数,只是执行析构函数体中的内容,并不会改变对象的生命周期。
构造函数和析构函数的顺序?
构造函数按照程序执行的顺序进行构造。
析构函数的执行顺序由对象的生命周期来决定:
堆内存的数据是人为释放,当你忘了人为释放时在程序结束后会自动释放;
栈的内存在函数结束以后就释放,析构函数的顺序和构造函数相反。
静态数据区的内存在程序结束以后才释放,同样和构造的顺序相反。
对象的内存空间有多大?
等于对象的成员变量的内存大小之和(满足字节对齐)当对象没有成员变量,对象的内存大小为1个字节
总结:
定义一个类,默认有哪些成员函数和运算符可以直接使用?1.构造函数
2.析构函数
3.拷贝构造函数
4.赋值运算符
5.&取地址运算符
四、静态成员
加上static修饰的成员叫静态成员,特点:属于该类的所有对象共享的
1.静态成员变量 本质上是全局变量,所以需要在全局范围声明,静态成员变量的内存在静态数据区,只有一份,不在对象的内存空间内。
2.静态成员函数 可以通过类名::函数名,直接调用静态成员函数,静态成员函数没有this指针。静态成员函数访问不了非静态的成员变量非静态成员函数可以访问静态成员变量
五、只读成员
被const修饰的成员叫只读成员,只读成员只能读不能写,不能做左值。
1.只读成员变量 在初始化的时候只能用初始化列表
2.只读成员函数 不能修改成员变量的值。只读成员函数不能调用非只读的成员函数,非只读的成员函数可以调用只读的成员函数
3.只读对象 该对象只能读不能写 mutable 关键字 (可变的)
被mutable修饰的变量不受const的约束三、友元
类的好友叫友元。友元可以访问类的私有成员。
1.外部函数是友元 ***** 该外部函数可以访问本类的私有成员
2.外部类是友元 *** 外部友元类的所有成员函数都可以访问本类的私有成员
3.外部类的成员函数是友元 *** 只有声明为友元的成员函数可以访问本类的私有成员,其他的成员函数不行
友元具不具有传递性?
友元不具有传递性
友元的声明不受访问限定符的影响。总结什么是封装,封装有什么作用?
1.定义类,类中有数据和方法,模块化编程,提高编程的效率。
2.通过访问限定符,确定哪些成员是隐藏的,哪些是暴露在外的接口,为了数据安全性。
友元破坏了封装,需要谨慎使用。
六、运算符重载
为什么要进行运算符重载?
1.运算符只对基本数据类型有效,对自定义的类类型无效。对象之间的运算必须要进行运算符重载
2.使用用运算符重载,使对象之间的运算变得简单,方便。
大部分运算符都可以被重载,只有如下不能:
成员运算符. 三目运算符?: sizeof运算符 作用域运算符::
运算符重载的本质是特殊的函数:(函数名特殊)
返回值类型 operator 运算符(入参列表。。。)
{
函数体。。。。
}
类有哪些函数:
1.成员函数 类的组成部分,可以访问类的私有成员,有this指针指代当前对象
2.友元函数 不是类的组成部分,可以类访问私有成员,没有this指针
3.非友元的外部函数 不能访问类的私有成员成员函数和友元函数做运算符重载有什么区别?
友元函数比成员函数做相同的运算符重载多一个入参。原因:成员函数有this指针可以指代一个对象。
注意:运算符重载不能改变运算符的优先级和含义。
七、数据封装
所有的 C++ 程序都有以下两个基本要素:
程序语句(代码):这是程序中执行动作的部分,它们被称为函数。
程序数据:数据是程序的信息,会受到程序函数的影响。
封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。数据封装引申出了另一个重要的 OOP 概念,即数据隐藏。
数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。数据抽象
数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节。
数据抽象是一种依赖于接口和实现分离的编程(设计)技术。
举一个现实生活中的真实例子,比如一台电视机,您可以打开和关闭、切换频道、调整音量、添加外部组件(如喇叭、录像机、DVD 播放器),但是您不知道它的内部实现细节,也就是说,您并不知道它是如何通过缆线接收信号,如何转换信号,并最终显示在屏幕上。
因此,我们可以说电视把它的内部实现和外部接口分离开了,您无需知道它的内部实现原理,直接通过它的外部接口(比如电源按钮、遥控器、声量控制器)就可以操控电视。
数据抽象的好处
数据抽象有两个重要的优势:
类的内部受到保护,不会因无意的用户级错误导致对象状态受损。类实现可能随着时间的推移而发生变化,以便应对不断变化的需求,或者应对那些要求不改变用户级代码的错误报告。
如果只在类的私有部分定义数据成员,编写该类的作者就可以随意更改数据。如果实现发生改变,则只需要检查类的代码,看看这个改变会导致哪些影响。如果数据是公有的,则任何直接访问旧表示形式的数据成员的函数都可能受到影响。