c++复习--类和对象


目录

 

一、 类和对象(熟练掌握) 

 1. 面向对象和面向过程的理解

2. 面向对象三大特性是什么?

2.1. 封装

2.2 继承

2.3 多态

3. 8个默认成员函数

​3.1 构造和析构

3.1.1构造函数

      3.2 拷贝构造和拷贝赋值

3.2.1 拷贝构造

3.2.2 拷贝赋值

       3.3 移动构造和移动赋值

3.3.1 移动构造

3.3.2 移动复制

       3.4 operator& 不关注

       3.5什么情况下会默认生成?默认生成的都干了什么?

3.5.1什么情况下会默认生成

3.5.2默认生成的都干了什么?

       3.6 构造函数初始化列表

3.6.1 初始化列表价值

3.6.2 哪些成员必须在初始化列表初始化        

4. 对象实例化

4.1 对象大小计算--(注意)内存对齐

4.2 空类的大小?为什么是1

5. this

5.1 什么是this指针

5.2 this存在哪?

​编辑哪些运算符不能重载

.运算符重载意义是什么

7. static成员

8. 友元

8.1 友元函数

8.2 友元类


一、 类和对象(熟练掌握)
   1. 面向对象和面向过程的理解

面向对象:关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。典型语言又c++,java

面向过程:关注的是过程,分析出求解问题的步骤,典型语言是C语言,C语言通过函数调用逐步解决问题。

2. 面向对象三大特性是什么?

2.1. 封装

封装是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。 封装本质上是一种管理,让用户更方便使用类。

比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。

2.2 继承

2.3 多态

3. 8个默认成员函数

3.1 构造和析构

3.1.1构造函数



 

3.1.2析构函数 

 更对详细参考(70条消息) 类和对象—6个默认成员函数_对象的默认成员_秋秋是个小菜鸡的博客-CSDN博客

      3.2 拷贝构造和拷贝赋值

3.2.1 拷贝构造

3.2.2 拷贝赋值

 

拷贝赋值与拷贝构造的区别:

拷贝构造函数是一个对象初始化一块内存区域,这块内存就是新对象的内存区,而赋值构造函数时对于一个已经被初始化的对象来进行赋值操作。

拷贝赋值,拷贝构造,构造函数三者使用场景

对象不存在,且没用别的对象来初始化,就是调用了构造函数;

对象不存在,且用别的对象来初始化,就是拷贝构造函数

对象存在,用别的对象来给它赋值,就是赋值函数


       3.3 移动构造和移动赋值

3.3.1 移动构造

 

3.3.2 移动复制

移动赋值和移动构造类似,区别类似于拷贝构造和拷贝赋值


       3.4 operator& 不关注

取地址及const取地址操作符重载
这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!


       3.5什么情况下会默认生成?默认生成的都干了什么?

3.5.1什么情况下会默认生成

我们定义一个空类。编译器会为我们默认生成一些函数。如果我们没有声明,编译器会帮我生成一个拷贝构造函数、一个拷贝赋值操作符和一个析构函数。同时如果我们声明构造函数的话,也会生成一个默认的构造函数

3.5.2默认生成的都干了什么?

1、默认构造函数不带任何参数,在对象初始化的时候调用。例如 Empty e1;
2、默认copy construct(拷贝构造)函数,用一个对象初始化另一个新对象的时候调用。例如Empty e2 = e1;
3、默认copy assignment(赋值)操作符,赋值的时候调用. 例如 Empty e2 ; e2 = e1;
4、默认析构函数,对象析构的时候调用.

说明:默认拷贝构造函数和默认赋值函数的实现基本上是一样的。会一一拷贝对象中的non-static成员数据。如果成员数据是基本类型,则直接进行赋值操作 e1.a=e2.b;

如果成员数据是自定义类型,则调用数据成员对应的默认拷贝构造函数,e1.a(e1.b);

如果数据对象是数组,则对每个元素进行拷贝操作 e1.arrayi;

copy construct 和 copy assignment 的区别在于调用场景不同。

如果是生成一个新对象则用 copy construct,

        例如 Empty e1 = e2(e1是个新对象);

如果是赋值一个已有的对象则用copy assignment,

        例如 Empty e1, e1 = e2(e1 是个已有的对象);


       3.6 构造函数初始化列表

 初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括 号中的初始值或表达式。 注意:每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

 

class Date
{
public:
 Date(int year, int month, int day)
 : _year(year)
 , _month(month)
 , _day(day)
 {}
 
private:
 int _year;
 int _month;
 int _day;
};


3.6.1 初始化列表价值

1.尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化

2.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关


3.6.2 哪些成员必须在初始化列表初始化        

  1.  引用成员变量
  2. const成员变量
  3. 自定义类型成员(且该类没有默认构造函数时)

4. 对象实例化

用类类型创建对象的过程,称为类的实例化

1. 类是对对象进行描述的 ,是一个 模型 一样的东西,限定了类有哪些成员,定义出一个类 并没有分配实际 的内存空间 来存储它
2. 一个类可以实例化出多个对象, 实例化出的对象 占用实际的物理空间,存储类成员变量


4.1 对象大小计算--(注意)内存对齐

通过下面这段 代码及结构我们来分析一下
#include<iostream>
using namespace std;
// 类中既有成员变量,又有成员函数
class A1 {
public:
	void f1() {}
private:
	int _a;
};
// 类中仅有成员函数
class A2 {
public:
	void f2() {}
};
// 类中什么都没有---空类
class A3
{};
int main()
{
	cout << sizeof(A1)<<endl;
	cout << sizeof(A2) << endl;
	cout << sizeof(A3) << endl;

	return 0;

}

结论:一个类的大小,实际就是该类中成员变量之和,当然要注意内存对齐

 

4.2 空类的大小?为什么是1

空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。
(或者我们这样来思考:如果一个空类没有空间,那我们之前提到的默认生成的函数怎么办)
ps:结构体内存对齐规则
1. 第一个成员在与结构体偏移量为 0 的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS 中默认的对齐数为 8
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是
所有最大对齐数(含嵌套结构体的对齐数)的整数倍。


5. this


5.1 什么是this指针

C++ 编译器给每个 非静态的成员函数 增加了一个隐藏的指针参 数,让该指针指向当前对象 ( 函数运行时调用该函数的对象 ) ,在函数体中所有 成员变量 的操作,都是通过该 指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成
this指针的特性
1. this 指针的类型:类类型 * const ,即成员函数中,不能给 this 指针赋值。
2. 只能在 成员函数 的内部使用
3. this 指针本质上是 成员函数 的形参 ,当对象调用成员函数时,将对象地址作为实参传递给 this 形参。所以对象中不存储 this 指针
4. this 指针是 成员函数 第一个隐含的指针形参,一般情况由编译器通过 ecx 寄存器自动传递,不需要用 户传递


5.2 this存在哪?

 this指针本质上是成员函数的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针
6. 运算符重载


哪些运算符不能重载

这5个不能重载

.*

::

sizeof

?:

.
运算符重载意义是什么

 C++为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字 operator 后面接需要重载的运算符符号
函数原型: 返回值类型  operator 操作符 ( 参数列表 )


7. static成员

声明为 static 的类成员 称为 类的静态成员 ,用 static 修饰的 成员变量 ,称之为 静态成员变量 ;用 static 修饰 成员函数 ,称之为 静态成员函数 静态成员变量一定要在类外进行初始化
特性
1. 静态成员 所有类对象所共享 ,不属于某个具体的对象,存放在静态区
2. 静态成员变量 必须在 类外定义 ,定义时不添加 static 关键字,类中只是声明
3. 类静态成员即可用 类名 :: 静态成员 或者 对象 . 静态成员 来访问
4. 静态成员函数 没有 隐藏的 this 指针 ,不能访问任何非静态成员
5. 静态成员也是类的成员,受 public protected private 访问限定符的限制


8. 友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
友元分为: 友元函数 友元类

8.1 友元函数

问题:现在尝试去重载 operator<< ,然后发现没办法将 operator<< 重载成成员函数。 因为 cout 的输出流对 象和隐含的 this 指针在抢占第一个参数的位置 this 指针默认是第一个参数也就是左操作数了。但是实际使用中cout 需要是第一个形参对象,才能正常使用。所以要将 operator<< 重载成全局函数。但又会导致类外没办 法访问成员,此时就需要友元来解决。operator>> 同理。
友元函数 可以 直接访问 类的 私有 成员,它是 定义在类外部 普通函数 ,不属于任何类,但需要在类的内部声
明,声明时需要加 friend 关键字。
class Date
{
 friend ostream& operator<<(ostream& _cout, const Date& d);
 friend istream& operator>>(istream& _cin, Date& d);
public:
 Date(int year = 1900, int month = 1, int day = 1)
 : _year(year)
 , _month(month)
 , _day(day)
 {}
private:
 int _year;
 int _month;
 int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
 _cout << d._year << "-" << d._month << "-" << d._day;
 return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{
 _cin >> d._year;
 _cin >> d._month;
 _cin >> d._day;
 return _cin;
}
int main()
{
 Date d;
 cin >> d;
 cout << d << endl;
 return 0;
}
说明 :
友元函数 可访问类的私有和保护成员,但 不是类的成员函数
友元函数 不能用 const 修饰
友元函数 可以在类定义的任何地方声明, 不受类访问限定符限制
一个函数可以是多个类的友元函数
友元函数的调用与普通函数的调用原理相同

8.2 友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
友元关系是单向的,不具有交换性。
如果 B A 的友元, C B 的友元,则不能说明 C A 的友元。
友元关系不能继承.
class Time
{
 friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成
员变量
public:
 Time(int hour = 0, int minute = 0, int second = 0)
 : _hour(hour)
, _minute(minute)
 , _second(second)
 {}
 
private:
 int _hour;
 int _minute;
 int _second;
};
class Date
{
public:
 Date(int year = 1900, int month = 1, int day = 1)
 : _year(year)
 , _month(month)
 , _day(day)
 {}
 
 void SetTimeOfDate(int hour, int minute, int second)
 {
 // 直接访问时间类私有的成员变量
 _t._hour = hour;
 _t._minute = minute;
 _t._second = second;
 }
 
private:
 int _year;
 int _month;
int _day;
 Time _t;
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值