旅游网站建设方案简介,做网站的第一步,我的世界怎么做神器官方网站,做社区网站用什么程序目录1.面向过程和面向对象初步认识2.类的引入3.类的定义4.类的访问限定符及封装4.1访问限定符4.2封装5.类的作用域6.类的实例化7.类对象模型7.1 如何计算类对象的大小8.this关键字如果说我们对C的初步认识#xff0c;是觉得C是对C语言不足之处的进行修补#xff0c;在认识完类…
目录1.面向过程和面向对象初步认识2.类的引入3.类的定义4.类的访问限定符及封装4.1访问限定符4.2封装5.类的作用域6.类的实例化7.类对象模型7.1 如何计算类对象的大小8.this关键字如果说我们对C的初步认识是觉得C是对C语言不足之处的进行修补在认识完类与对象后我们会对C产生新的认识 1.面向过程和面向对象初步认识 C语言是面向过程的关注的是过程分析出求解问题的步骤通过函数调用逐步解决问题 C是基于面向对象的关注的是对象将一件事情拆分成不同的对象靠对象之间的交互完成 2.类的引入 C语言结构体中只能定义变量在C中结构体内不仅可以定义变量也可以定义函数。 比如 之前在数据结构初阶中用C语言方式实现的栈结构体中只能定义变量现在以C方式实现 会发现struct中也可以定义函数 对于C中的struct属性成员变量方法函数
①兼容C中struct中的所有用法
②升级成了类
举例如下
typedef int DataType;
//Stack为类名
struct Stack
{ //①属性DataType *_array;size_t _capacity;size_t _size;//②方法void Init(size_t capacity){//...}void Push(const DataType data){//...}void Destroy(){//...}
};int main()
{ //s是对象Stack s;//【对象.方法】、【对象.属性】s.Init(10);s.Push(1);s.Push(2);s.Push(3);cout s.Top() endl;s.Destroy();return 0;
}一般的在定义成员变量名时常常在前面加上前杠例如
class Date
{public:int _year;int _month;int _year;public:void Init(){//...}
}3.类的定义
1.定义
class className
{// 类体由成员函数和成员变量组成
}; // 一定要注意后面的分号class为定义类的关键字 ClassName为类的名字 **{}**中为类的主体注意类定义结束时后面分号不能省略
类的两种定义方式
①声明和定义全部放在类体中需注意成员函数如果在类中定义编译器可能会将其当成内联函数处理
class People {
public:int age;int sex;int height;public:void Eat() {cout people can eat endl;}void Run() {cout people can run endl;}
};②类声明放在.h文件中成员函数定义放在.cpp文件中注意 成员函数名前需要加类名 为什么要声明和定义分离 加强代码的可阅读性 在cpp文件种对成员函数进行声明注意标识该函数的类域即类名 2.对象
和结构体一样类的定义是一个类型要访问它的成员属性、方法就要实例化对象
一个类可以定义多个对象
4.类的访问限定符及封装
4.1访问限定符 ① public修饰的成员在类外可以直接被访问
② protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
③访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
④如果后面没有访问限定符作用域就到 } 即类结束
⑤class的默认访问权限为private struct默认为public(因为struct要兼容C)
4.2封装
面向对象的三大特性 封装、继承、多态
在类和对象阶段主要是研究类的封装特性那什么是封装呢
封装将数据和操作数据的方法进行有机结合隐藏对象的属性和实现细节仅对外公开接口来和对象进行交互
因此我们将属性置为private通过public方法公有成员来实现对属性的操作 因此封装的目的不是为了阻止对数据的访问而是规定一种规范的方法让我们对其访问 5.类的作用域
类定义了一个新的作用域类的所有成员都在类的作用域中 在类体外定义成员时需要使用**:*作用域操作符指明成员属于哪个类域
class Person
{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int _age;
};// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{cout _name _gender _age endl;
}6.类的实例化
常见错误
Person::_age1; //wrong
Person::PrintPersonInfo(); //wrong正确的
//通过对象
Person p1;
p1._age10;
p1.PrintPersonInfo();//通过指针
Person p2;
Person* ptrp2;
ptr-_age20;7.类对象模型
7.1 如何计算类对象的大小
引入
class A
{
public:void PrintA(){cout _a endl;}
private:char _a;
};这里类A的大小是多少呢 结果是1我们发现类存储时只存了变量属性
而类对象的大小规则同结构体内存对齐规则
【补充】结构体内存对齐规则
1.第一个成员在与结构体偏移量为0的地址处
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
注意对齐数 编译器默认的一个对齐数与该成员大小的较小值VS中默认的对齐数为8
3.结构体总大小为最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4.如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
①例内存对齐的体现 ②例空类大小为1——占位不存储有效数据标识对象存在 8.this关键字
1.引入
class Date {
private:int _year;int _month;int _day;
public:void Init(int year, int month, int day) {_year year;_month month;_day day;}
public:void Print() {cout _year _month _day endl;}
};对于上述类有这样的一个问题
Date类中有 Init 与 Print 两个成员函数函数体中没有关于不同对象的区分那当d1调用 Init 函数时该函数是如何知道应该设置d1对象而不是设置d2对象呢
C中通过引入this指针解决该问题即 C编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数让该指针指向当前对象(函数运行时调用该函数的对象)
即
void Print(Date* this)
{cout this-_year this-_month this-_day endl;
}注意this指针的定义和传递是由编译器完成我们不能去做但是我们可以在类里面用this指针
这里的this代表d1和d2对象的地址 this指针与const修饰问题
const Date* p1; //修饰的是指针指向的对象 *p1
Date const* p2; //修饰的是指针指向的对象 *p2
Date* const p3; //修饰的是本身 p32.this指针存在哪
this是一个形参一般存在栈帧中vs下进行了优化使用了ecx寄存器传递3.this指针可以为空吗
// 1.下面程序编译运行结果是 A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void Print(){cout Print() endl;}private:int _a;
};int main()
{A *p nullptr; //p这里是一个空指针p-Print(); //不发生解引用因为成员函数的地址不在对象中在公共代码区域return 0;
}
//正常运行// 2.下面程序编译运行结果是 A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:void PrintA(){cout _a endl; //本质是this-_a}private:int _a;
};int main()
{A *p nullptr; //发生空指针的解引用p-PrintA();return 0;
}
//运行崩溃