本篇目标
1.面向过程和面向对象初步认识
2.类的引入
3.类的定义
4.类的限定访问符及封装
5.类的作用域
6.类的实例化
7.类的对象大小的计算
8.类成员函数的this指针
一、面向过程和面向对象初步认识
c语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题
而C++是面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成
二、类的引入
C语言中结构体只能定义变量,而在C++中,结构体不仅可以定义变量,还可以定义函数。比如:在我之前用c语言实现的栈,结构体中只能定义变量,现在以C++的方式实现,会发现在结构体中可以定义函数
注意:在C++中,结构体名称据可以代表类型(ListNode* = strcut ListNode*)
三、类的定义
class className
{
//类体:由成员函数和成员变量构成
}; //注意这里的分号
class为定义类的关键字,className为类的名字,{}中的为类的主体,注意类定义结束后后面的分号不能省略。
类体中的内容称为类的成员:类中的变量称为类的属性或者成员变量;类中的函数称为类的方法或者成员函数。
类的两种定义方式:
1.声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能将其当成内联函数来处理
2.定义和声名分离,类的声明放在.h头文件,成员函数定义放在.cpp文件,注意:成员函数名前要加类名::
一般情况下,采用分离的形式
四、类的访问限定符和封装
4.1 访问限定符
C++实现封装的方式:用缧降对象的属性和方法结合在一起(方便管理),让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
注:通常把成员函数设为公有,把成员变量设为私有
使用说明:
1.public修饰的成员在类外可以直接被访问
2.protected和private修饰的成员在类外不能直接被访问
3.访问权限作用域从访问限定符出现的位置开始到下一个访问限定符出现时为止
4.如果后面没有访问限定符,作用域到 } 截至
5.class的默认访问权限为private,struct为public(因为public要兼容C)
4.2 封装
面向对象的三大特性:继承、封装、多态
在类和对象种族要研究类的封装特性,封装是:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,进对外公开接口和对象进行交互
五、类的作用域
C++中的作用域:局部域、全局域、类域、命名空间域
类定义了一个全新的作用域,类的所有成员都在类的作用域中。在类外定义成员时,需要用 :: 作用域操作符周明成员属于哪个类域
六、类的实例化
6.1 声明和定义区别
声明:表明名字 定义:开出空间
6.2 类的实例化
用类类型创建对象的过程,称为类的实例化
1.类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储他
2.一个类可以实例化出多个对象,实例化出的对象,占用实际的物理空间,存储成员变量
Person类并没有实际的物理空间
3.类和对象的关系
七、类对象模型
7.1 计算类对象的大小
类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?
1.类对象储存方式的猜测
缺陷:每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一 个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。那么 如何解决呢?
结论:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐。 注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象,成员函数都放在公共代码区
八、this指针
8.1 this指针的引出
先来定义一个日期类Date
问题来了,Date中有Init和Print两个成员函数,函数体中没有关于不同对象的区分,那么当d1调用Init函数时,该函数是如何知道应该设置d1对象,而不是d2对象呢?
C++中通过引入this指针来解决这个问题,即:C++编译器给每个“非静态的成员函数”增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有"成员变量"的操作,都是通过该指针去访问。只不过所有的操作都是由编译器自动完成。
8.2 this指针的特性
1.this指针的类型:类类型*const,即成员函数中,不能对this指针赋值
类类型
:这是指针指向的对象的类型。它可以是任何有效的 C++ 类型。*
:表示这是一个指针。const
:表示指针所指向的数据是常量,不能通过这个指针来修改它。.
2.this指针只能在成员函数的内部使用
3.this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传给this形参,所以对象中不存储this指针
4.this指针是“成员函数”第一个隐含的指针形参,一般由编译器通过ecx寄存器自动传递,不需要用户传递
九、C++实现栈
#pragma once
#include<iostream>
using namespace std;
//C++写的话,把类写在头文件里
//跟之前差不多
typedef int DataType;
class Stack
{
public:
void Init()
{
_array = (DataType*)malloc(sizeof(DataType) * 3);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = 3;
_size = 0;
}
void Push(DataType data)
{
CheckCapacity();
_array[_size] = data;
_size++;
}
void Pop()
{
if (Empty())
return;
_size--;
}
DataType Top() { return _array[_size - 1]; }
int Empty() { return 0 == _size; }
int Size() { return _size; }
void Destroy()
{
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
}
}
private:
void CheckCapacity()
{
if (_size == _capacity)
{
int newcapacity = _capacity * 2;
DataType* temp = (DataType*)realloc(_array, newcapacity *
sizeof(DataType));
if (temp == NULL)
{
perror("realloc申请空间失败!!!");
return;
}
_array = temp;
_capacity = newcapacity;
}
}
private:
DataType* _array;
int _capacity;
int _size;
};
int main()
{
Stack s;
s.Init();
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
printf("%d\n", s.Top());
printf("%d\n", s.Size());
s.Pop();
s.Pop();
printf("%d\n", s.Top());
printf("%d\n", s.Size());
s.Destroy();
return 0;
}
十、代码兴国