第十三章_类和对象

目录

1.strcpy和memcpy的区别

2.exit

一、基本概念1

1.类的封装性

2.定义一个类 

 3.成员函数 类中声明,类外实现 

二、构造函数

1. 构造函数 和 析构函数

2. 构造函数 的 概述

3. 构造函数 的 定义方法

三、析构函数

 1.析构函数的定义方法

2.析构函数的调用顺序

 四、拷贝构造函数

1.拷贝构造的定义形式

2.拷贝构造 和 无参构造、有参构造 的关系

3.拷贝构造的几种调用形式 

 4.拷贝构造的深拷贝

 五、初始化列表

1.对象成员

 2.初始化列表

 六、explicit关键字

七、类的对象数组

 八、动态对象创建

1. c创建动态对象

九、静态成员

1.静态成员变量 

 2.静态成员函数 

3.单例模式设计 

 十、c++面向对象模型

 1.成员变量 和 函数的存储

 2.this指针

2.2 this指针的应用

十一、友元

1.普通全局函数 作为 类的友元

2.类的某个成员函数 作为另一个类的友元

 3.友员注意事项

4.友员案例

十二、运算符重载

1.基本概念

2.可以重载的运算符

3.重载 输出运算符 

4.重载 输入运算符 

5.重载 加法运算符 

6.重载 相等运算符 

7.重载 加加减减 运算符 

8.重载 函数调用运算符

 9.智能指针(指针运算符(*、->)重载)


插入:

1.strcpy和memcpy的区别:

(头文件都是<string.h>)

 1、复制的内容不同。 strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。

2、复制的方法不同。 strcpy不需要指定长度,它遇到被复制字符的串结束符"0"才结束,所以容易溢出。 memcpy则是根据其第3个参数决定复制的长度。

int* tmp = new int[capacity];                    //申请空间

memset(tmp, 0, sizeof(int)  * capacity);  //tmp每个元素赋值0,即 清空空间

memcpy(tmp, arr, sizeof(int) * size);       //arr的内容拷贝到tmp,指定大小(arr的size)13

strcpy(tmp,arr);                                     //arr的内容拷贝到tmp

2.exit

进程的退出最好是用三个终止函数( exit、_exit、 _Exit )其中的一个(后两者属于系统调用),当然建议 exit 即可

正常退出:exit(0)、exit( )

异常退出:exit(除0外的其他值)

0/其他值 表示退出状态,即把退出状态传给exit函数,正常和异常 表现为后期操作系统内部处理过程不同,但最后都会退出。

完整写是system.exit( );

一、基本概念1

1.类的封装性

类 将具有共性的 数据和方法 封装在一起,加以权限区分,用户只能通过 公共方法 访问 私有数据。

类的权限分为:private(私有)、protected(保护)、public(公有)

在类的外部,有public修饰的成员才可以被访问。在没有涉及继承和派生时,private和protected是同等级的,外部不允许访问。用户在类的外部 可以通过public方法 间接访问 private和protected是数据。

2.定义一个类 

 class关键字(注意有分号)

class Data
{
//成员变量
private: //类中不写权限默认private(私有)
int a;
protected:
int b;
public:
int c;

//成员方法
void showData(void)
{cout<<a<<b<<c<<endl;}

};

int main()
{
//类实例化一个对象
Data ob;
//类外不能直接访问 类的私有和保护数据,公有数据可以。
cout<<ob.c<<endl;
//类中的成员函数和成员变量,需要对象调用。
ob.showData();
}

 设计一个类的步骤:

  • 确定有哪些成员变量,成员变量为私有
  • 确定操作这些变量的成员函数,成员函数为公有(Init函数+get函数+其他)

 3.成员函数 类中声明,类外实现 

 注意成员函数要加 ::,以表明所属,和全局函数区分

一般都是 成员函数 类中声明,类外实现 ,类定义在.h文件,成员函数实现在.cpp文件

*成员函数 一般比 全局函数 传的参数要少

     成员函数需要用某个成员变量去调用,传参时无需再传这个成员变量,因此参数变少。

二、构造函数

1. 构造函数 和 析构函数

构造函数 完成 初始化操作,析构函数 完成 清理操作。这2个函数都会被编译器自动调用。  

2. 构造函数 的 概述

类实例化对象的时候,系统自动调用构造函数,完成对象初始化。

如果用户不提供构造函数,编译器会自动添加一个默认的构造函数(空函数)。

如果用户定义了一个构造函数(不管是有参还是无参),编译器都不再提供构造函数。

(这也就意味着,如果定义了一个有参构造函数,但是定义了一个无参的类的话,编译器将因找不到无参构造函数而报错)

3. 构造函数 的 定义方法

构造函数名 和 类名 相同,没有返回值(连void都不可以),可以有参数,可以重载。权限为public(因为肯定要外部传初始值,私有就无法调用了) 

class Data{
public:
int mA;
public:
//无参构造函数
Data()
{mA=0;}
//有参构造函数
Data(int a)
{mA=a;}
//析构函数
~Data()
{cout<<mA<<endl;}
};

int main(){
//隐式调用无参构造函数(编译器自动调用)(推荐)
Data ob1;
//显式调用无参构造函数
Data ob2=Data();//这里其实也是先创建匿名对象,再把匿名对象的值赋给对象ob2
//隐式调用有参构造函数(推荐)
Data ob3(10);
//显式调用有参构造函数
Data ob4=Data(10);

//匿名对象(无参)
//当前语句结束,立即释放
Data();
Data(20);

//构造函数隐式转换(当 类中只有一个数据成员 时才可以这样直接赋值)
Data ob5=100;

三、析构函数

 1.析构函数的定义方法

  • 函数名和类名称相同,在函数名前加~,没有返回值类型,没有函数形参(不能被重载)。
  • 当对象生命周期结束的时候,系统自动调用析构函数。
  • 一般情况下,系统默认的空的析构函数就足够,不需要再写析构函数;
  • 但如果一个类有 指向堆区空间的 指针成员,这个类必须写析构函数。

(因为析构函数只释放了指针变量,没有释放指针变量所指的堆区空间。需要写析构函数去释放指针成员所指向的堆区空间)

(示例见上)

2.析构函数的调用顺序

栈,先定义的后释放

 四、拷贝构造函数

本质:有参构造函数 

拷贝构造的调用时机:旧对象给新对象初始化,就会调用拷贝构造函数。

如果用户不提供拷贝构造,编译器会自动提供一个默认的拷贝构造,完成赋值动作(浅拷贝)。

只有存在指针成员变量,需要深拷贝时,才会去自己写拷贝构造函数。

1.拷贝构造的定义形式

名字 同 类名称,参数当前类的常引用(特征)

 

2.拷贝构造 和 无参构造、有参构造 的关系

如果用户定义了 拷贝构造 或者 有参构造,都会屏蔽 无参构造。

如果用户定义了 无参构造 或者 有参构造,不会屏蔽 拷贝构造。

3.拷贝构造的几种调用形式 

3.1旧对象给新对象初始化

 

3.2普通对象作为 函数参数,调用函数时

3.3普通对象 作为 函数返回值 ,返回值时

vs会发生拷贝构造:

  1. 函数 return 的作用:返回值+结束当前函数
  2. 返回的值 放在了 栈区的临时区域(要在临时区的固定地方申请一个匿名对象,然后把值赋给这个匿名对象,就相当于旧对象给新对象初始化)
  3. 用ob2去接函数返回值(即 接匿名空间的值,不然匿名空间函数执行完就释放了。即使没有Ob2接也会发生拷贝构造)

Qtcreater、linux不会发生拷贝构造:

用ob2直接接管ob1空间,而不需要临时匿名对象(即ob1空间没被释放,直接给ob2了)

3.4给对象取别名,不会调用拷贝构造

 

 4.拷贝构造的深拷贝

如果类中没有指针成员,不用实现 拷贝构造 和 析构函数 。

如果类中有 指针成员 且指向堆区空间,必须实现 析构函数 释放指针成员指向的堆区空间,并且必须实现 拷贝构造 完成深拷贝。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值