Tables | 关键字 |
---|---|
1.什么是面向对象 | |
2.类 | 概念,特点 |
3.类的大小 | 为什么要内存对齐?内存对齐的计算?空类的计算 |
4.类的4个默认成员函数的详细使用 |
1.什么是面向对象
官方定义:
面向对象是一种思想,是基于面向过程而言的。就是说面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节;这种思想是将数据作为第一位,而方法或者说是算法作为其次,这是对数据一种优化,操作起来更加的方便,简化了过程。面向对象有三大特征:封装性、继承性、多态性,
官方定义太过抽象,含糊,为适应大多数场景,所以难以理解。下面来针对C++理解什么是面向对象。
来看下面举例:
“分析下面需求实现的方案
我的午餐 - 西红柿鸡蛋打卤面
方案一:
实现的大致步骤
1>购买西红柿,鸡蛋和面粉
2>打卤
3>和面,擀面条,煮面
4>午餐成功做好了
“方案一的特点
强调的是做 西红柿鸡蛋打卤面 这件事情的具体的实现步骤,强调每一个步骤都是”我”自己做的,”我”是绝对的执行者.
方案二:
1.实现大致步骤
1>使用手机下载”美团外卖”
2>搜索西红柿鸡蛋打卤面,下单
3>午餐成功送到
“方案二的特点
强调的”美团外卖”在整个事件中起到的作用,”美团外卖”是这个事件的主角.”我”是一个指挥者.
总结:面向对象和面向过程
1.面向过程:对于一个问题.强调事情解决的每一个步骤都是当事人自己亲自实现,这种解决问题的思路叫面向过程,就像方案一自己动手煮面的过程
2.面向对象:对于一个问题.强调事情解决过程通过当事人找到一个专门解决这类问题的专家来帮助自己解决问题.当事人扮演”指挥者”,这种解决问题的思路叫面向对象,就像方案二用美团外卖下单打卤面的过程。
3.官方定义里的对象就是指类的实例化。(类的实例化就好比盖一栋大楼,首先会在设计图上设计好这栋大楼的具体框架,然后 工程师就会按照设计图纸来建造大楼。类就好比图纸,它包含了对象的大体框架,对象实例化就好比按照图纸,产生一个实际的大楼一样。
)
“面向对象和面向过程的侧重点
1.面向过程和面向对象只是解决问题的不同方案,不同思路.
2.面向过程:强调把控实现的细节.
3.面向对象:找专家解决问题,这些专家很多都在框架中已经存在,可以直接引用.如果没有提供,可以自己创造,之后还可以复用—> 高效和复用.
特点:封装性 ,继承,多态
先来了解封装特性:
1:将数据和方法封装在类里
2:使用状态限定符,想给你看的数据设置成公有,不想给你看的设置成私有。对数据和方法进行限定访问。实现高内聚,低耦合。
2.类的基础知识
C++ 类定义
定义一个类,本质上是定义一个数据类型的蓝图。这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
类的结构:由成员变量和成员函数组成。成员变量指定对象中应该包含的数据,成员函数指定对象可以执行那些操作。
类定义是以关键字 class /struct开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。
类的简单定义:
先来看一个简单类定义的格式:
类的定位:
本文讨论的类也是C++数据结构中自定义类型的一种。由于这是C++种特有的一种数据类型,所以特地拿出来讨论,前面几种数据类型和C语言使用相同(C++兼容C),这里不再讨论。
类的限定符
class类默认成员为私有,struct默认成员为公有。
类的作用域
- 每个类都定义了自己的作用域,类的成员(成员函数/成员变量)都在类的这个作用域内,成员函数内可任意访问成员变量和其它成员
函数。 - 对象可以通过. 直接访问公有成员,指向对象的指针通过->也可以直接访问对象的公有成员。
- 在类体外定义成员,需要使用:: 作用域解析符指明成员属于哪个类域。
成员函数的声明定义
1.在类域以内定义成员函数
class Person
{
public:
void Display()
{
cout<<_name<<"-"<<_age<<"-"<<_id<<endl;
}
public:
char* _name;
int _age;
int _id;
};
2 在类外定义成员函数,需要加上作用域
class Person
{
public:
void Display()
public:
char* _name;
int _age;
int _id;
};
void Person::Display()
{
cout<<_name<<"-"<<_age<<"-"<<_id<<endl;
}
类实例化对象
1.类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。就好比生活中的雪糕模子,模子只有一个,且不占用任何食材。通过这个莫子可以产生多个雪糕,类也是同理。一个类可以产生多个对象。
2.一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间存储类成员变量。。就好比生活中的雪糕模子,模子只有一个,且不占用任何食材。通过这个莫子可以产生多个雪糕。类也是同理。一个类可以产生多个对象。
类的存储
1.由于类存储时,成员函数在公共区域,所以计算sizeof(类名)时,成员函数的大小不算在内。
2.所以每个对象的大小为类中所有成员变量的大小之和,当然这里也遵循内存对齐原则。
成员函数存在 进程虚拟地址空间的代码区。
运用实例
#include<iostream>
using namespace std;
class Person
{
public:
void Display()
{
cout<<_name<<"-"<<_age<<"-"<<_id<<endl;
}
public:
char* _name;
int _age;
int _id;
};
int main()
{
// .形式访问
Person p;
p._name="jack";
p._age=20;
p._id=123456;
p.Display();
//指针形式访问
Person *point=&p;
point->_name="Rose";
point->_age=21;
point->_id=654321;
point->Display();
return 0;
}
运行结果
[zyc@localhost lession_class]$ ./a.out
jack-20-123456
Rose-21-654321
常见报错:
1.成员变量私有,却在类外访问
class.cpp:18: error: ‘char* Person::_name’ is private
2.类定义完毕不加 ; 结尾
class.cpp:10: note: (perhaps a semicolon is missing after the definition of ‘Person’)
类的大小计算
首先来看实例:
#include<iostream>
using namespace std;
class A
{
char a;
int b;
short c;
};
class B
{
short c;
char a;
int b;
};
int main()
{
cout<<"sizeof(A)="<<sizeof(A)<<endl;
cout<<"sizeof(B)="<<sizeof(B)<<endl;
return 0;
}
运行结果
[zyc@localhost lession_class]$ ./a.out
sizeof(A)=12
sizeof(B)=8
那么问题来了:这些变量只是换了一下顺序,算出来的结果却不一样。
这里就要用内存对齐来解释这个原因了。
首先来看内存对齐规则。(先学会用再探究原因)
结构体内存对其规则:
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数=编译器默认的一个对齐数与该成员大小的较小值。
VS中默认的值为8
gcc中的默认值为4
3.结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体
的对齐数)的整数倍。
按照规则,我们来看刚才的例子。
变量A的存储(在linux下,默认对齐数:4)
同理,B的存储如下
从以上分析可得,
sizeof(A)=12
sizeof(B)=8
就不难理解了。经过内存对齐后,结构体的空间反而增大了。
**内存对齐原因?
1 内存访问不是一次访问一次一个字节,太浪费时间,某,到底一次访问多个字节(这个由硬件总线决定)。这里假设一次访问四字节。
空类的计算**