类与对象初步认识
C语言是面向过程的,关注的是过程,分析求解问题步骤,通过函数调用逐步解决问题
C++基于面向对象的(由于它要兼容C语言不是纯粹面向对象),关注的是对象,将事件拆分为不同对象,靠对象之间交互完成。
/* 指定基本类型:
- 决定数据对象需要的内存数量;(如:char占1字节内存,double占8字节内存等)
- 决定如何解释内存中的位;(long和float占内存大小相同,但它们数值转换的方法不同)
- 决定可使用数据对象执行的操作或方法;(如:int和指针类型占内存大小相同,但指针类型不能执行与整数相同的运算)
对于内置类型,其有关操作的信息被内置到编译器中;C++用户自定义类型时,需要自己提供这些信息。
类的引入
C语言的结构体只能定义变量;
C++结构体既可以定义变量,也可以定义函数。
结构体定义时用class 替换 struct
类的定义
struct/class className
{
// 类的成员变量和成员函数
};
类中的元素称为类的成员:类中的数据称为类的属性或者成员变量;类中的函数称为类的方法或者成员函数。
类声明:以数据成员的方式描述数据部分,以成员函数(方法)的方式描述公有接口;
类方法定义:描述如何实现类成员函数。
类的定义方式:
1. 声明和定义全放在类体中
#include <iostream>
using namespace std;
class Person
{
public:
void SetInfo(char* name, char* gender, int age)
{
strcpy(_name, name);
strcpy(_gender, gender);
_age = age;
}
void PrintInfo()
{
cout << _name << " " << _gender << " " << _age << endl;
}
public:
char* _name;
char* _gender;
int _age;
};
2. 声明放在.h文件中
class Person
{
void SetInfo(char* name, char* gender, int age);
void PrintPersonInfo();
char _name[20];
char _gender[3];
int _age;
};
类的定义放在.cpp文件中
#include <iostream>
#include "Person.h"
using namespace std;
void Person::SetInfo(char* name, char* gender, int age)
{
strcpy(_name, name);
strcpy(_gender, gender);
_age = age;
}
void Person::PrintInfo()
{
cout << _name << " " << _gender << " " << _age << endl;
}
类的访问限定符及封装
面向对象的三大特性
封装
将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互(初始化、更新、报告)。
数据隐藏(将数据放在类的私有部分);将函数放在类的私有部分;将类的函数定义与类声明放在不同文件中。
继承
可以让某个类型的对象获得另一个类型的对象的属性的方法。它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行拓展
多态
一个类实例的相同方法在不同情形有不同表现形式。使具有不同内部结构的对象可以共享相同的外部接口。
除此外面向对象还有五大原则+低耦合高内聚。
访问限定符
C++实现封装的方式:将类的属性与方法结合到一起,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
- public(公有)修饰的成员在类外可以直接被访问;
- protected(保护)和prviate(私有)修饰的成员在类外不能直接被访问;
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止;
- class的默认访问权限为private,struct为public(因为struct要兼容C语言)。
访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。
类的作用域
注意:
1.尽量避免成员函数的参数与成员变量同名;
2.成员变量在类中具有全局作用域属性;
3.在类体外定义成员,需要使用作用域解析符(::)来指明成员属于那个类。
类的实例化
概念:用类类型创建对象的过程,就称之为类的实例化。
1. 类只是一个模型,限定了类有哪些成员,定义出一个类并没有分配实际内存空间来存储它;
2.一个类可以实例化出多个对象,实例化出的对象,占用实际物理空间,存储类成员变量;
类对象模型
- 直接看:包含成员函数 + 成员变量
- 调用:调用同一个成员函数—指针(指向类中的成员变量)—>存储类中的成员函数
- 实际对象模型(类和对象):包含类中的"成员变量".
类对象大小
一个类大小,实际就是该类中“成员变量”之和(注意内存对齐);空类占一个字节。
结构体内存对齐:
- 第一个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的对齐数为8,gcc中的对齐数为4- 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
//设置对齐方式:
#program pack(num) //num字节的对齐
位域–>bit //只能在结构体中使用
类对象的存储方式
对象中只保存成员变量,成员函数存放在公共的代码段。
this指针
在前面曾经提到过:
每个对象中的数据成员都分别占有存储空间,如果对同一个类定义了n个对象,则有n组同样大小的空间以存放n个对象中的数据成员。但是,不同对象都调用同一个函数代码段。当不同对象的成员函数引用数据成员时,为保证引用的是所指定的对象的数据成员。C++在每个成员函数中都包含一个特殊的指针(this指针)(通过寄存器方式传递指针)。
this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。在函数体中所有成员变量的操作,都是通过this指针访问。
this指针保存当前对象地址(函数运行时调用该对象),即this指针指向当前对象,可以通过"->"访问该对象的成员。
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。
特征:
1. this指针的类型:类类型* const
2. 只能在“成员函数”的内部使用
3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
区别函数参数传递方式:
__cdecl // 函数调用约定 —> 参数压栈
__thiscall // 限制成员函数 —> 寄存器