当前位置:网站首页>类和对象:上
类和对象:上
2022-07-31 23:44:00 【懒惰的bit】
面向过程和面向对象初步认识
- C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题
- C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成
类的引入
#include<iostream>
using namespace std;
//C
struct Stack_C
{
int* a;
int top;
int capacity;
};
//C++
struct Stack_CPP
{
void Init()
{
a = 0;
top = capacity = 0;
}
void Push(int x)
{
// ...
}
void Pop()
{
// ...
}
int* a;
int top;
int capacity;
};
int main()
{
struct Stack_C st1;
//Stack是类名,也是一种类型,直接用就行了
Stack_CPP st2;
st2.Init();
st2.Push(1);
st2.Push(2);
st2.Push(3);
return 0;
}
- 在C语言中struct中只能定义成员变量
- 在C++中引入了类的概念,struct中不仅仅可以定义成员变量,还可以定义成员函数
类的定义
实现一
#include<iostream>
using namespace std;
class Person
{
//显示基本信息
void Show_information() {
cout << _name << _age << _area << endl;
}
char* _name;
char* _area;
int _age;
};
int main()
{
Person zhansan;
return 0;
}
- 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
实现二
- 类声明放在.h文件中,成员函数定义放在.cpp文件中,
- 注意:成员函数名前需要加类名::
类的定义补充说明
- 小函数,想成为inline,直接在类里面定义就可以
- 如果是大函数,应该声明和定义分离
类的访问限定符及封装
#include<iostream>
using namespace std;
class Stack
{
public:
void Init()
{
a = 0;
top = capacity = 0;
}
void Push(int x)
{
// ...
}
void Pop()
{
// ...
}
int Top()
{
return a[top - 1];
}
private:
//protected:
int* a;
int top;
int capacity;
};
int main()
{
Stack st;
st.Init();
st.Push(1);
st.Push(2);
st.Push(3);
//cout << st.a[st.top] << endl;
//cout << st.a[st.top-1] << endl;
cout << st.Top() << endl;
//st.a = nullptr;
return 0;
}
- public修饰的成员在类外可以直接被访问
- protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
- 如果后面没有访问限定符,作用域就到 } 即类结束。
- class的默认访问权限为private,struct为public(因为struct要兼容C)
C++中struct和class的区别是什么?
- C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private
封装
举个例子:取栈的栈顶

- C语言->没有办法封装,对于使用者来说这里的st.top可能是栈顶元素,也可能是栈顶的后一个元素,可以直接访问数据,但是不规范
- C++ -> 封装 必须规范使用函数访问数据,不能直接访问数据,
类的实例化
类不占用空间,在使用的时候发生类的实例化,才开辟了空间
- 规范的使用类的时候,是需要声明和定义分离的,开辟了空间叫定义,没有开辟空间的叫声明
- static 修饰的声明,只在当前文件可见,链接时没有放进符号表,所以两次打印的地址不同
- extern 修饰的声明,在链接时会放进符号表,所以两次打印的地址相同
- 注意:.h文件会在.cpp中展开,所以在.h文件中没有声明变量只定义变量,就会出现链接错误,重定义,
类对象模型
类对象的存储方式猜测
猜测一:对象中包含类的各个成员
- 缺陷:每个对象中成员变量是不同的,都调用同一份函数,每次调用相同的代码就会保存一次,多个对象的话,相同代码保存多次,浪费空间。
猜测二:代码只保存一份,在对象中保存存放代码的地址
- 这里在访问类成员函数的时候,是通过对象中保留了类成员函数表的指针,通过指针的解引用进行访问的,
猜测三:只保存成员变量,成员函数存放在公共的代码段
- 编译链接时就根据函数名去公共代码区找到函数地址
- C++类对象的存储方式是第三种,只保存成员变量,成员函数存放在公共的代码段
#include<iostream>
using namespace std;
class A1
{
public:
void PrintA()
{
cout << _a << endl;
}
void func()
{
cout << "void A::func()" << endl;
}
private:
char _a;
int _i;
};
class A2 {
public:
void f2() {}
};
class A3{
};
int main()
{
cout << sizeof(A1) << endl;
cout << sizeof(A2) << endl;
cout << sizeof(A3) << endl;
return 0;
}
- 一个类的大小,实际就是该类中”成员变量”之和,这里和C语言一样也会发生内存对齐
- 注意:空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。
成员变量命名规则的建议
驼峰法——单词和单词之间首字母大写间隔
class Date
{
public:
void Init(int year)
{
_year = year;
}
private:
int _year;
};
- 函数名、类名等所有单词首字母大写 DateMgr
- 变量首字母小写,后面单词首字母大写 dateMgr
- 成员变量,首单词前面加_ _dateMgr
this指针
#include<iostream>
using namespace std;
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year; // 年 -> 声明
int _month; // 月
int _day; // 日
};
int main()
{
Date d1;
d1.Init(2022, 7, 17);
Date d2;
d2.Init(2022, 7, 18);
d1.Print();
d2.Print();
return 0;
}
- Date类中有 Init与Print 两个成员函数,他们都是放在公共代码区中的,而函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,lnit这个函数如何知道应该对d1进行初始化,而不是给d2进行初始化
- C++中通过引入this指针解决该问题,即:
- C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,
- 让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。
- 只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
#include<iostream>
using namespace std;
class Date
{
public:
void Init(Date* const this, int year, int month, int day)
{
this->_year = year;
this->_month = month;
this->_day = day;
}
void Print(Date* const this)
{
cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}
private:
int _year; // 年 -> 声明
int _month; // 月
int _day; // 日
};
int main()
{
Date d1;
d1.Init(&d1,2022, 7, 17);
Date d2;
d2.Init(&d2,2022, 7, 18);
d1.Print();
d2.Print();
return 0;
}
- 这里我将编译器隐藏起来的this指针显示出来了,但这样编译器是会报错的,
- 注意:实参和形参位置不能显示传递和接收this指针,但是可以在成员函数内部使用this指针
this指针的特性
- this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
- 只能在“成员函数”的内部使用
- this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
- this指针是“成员函数”第一个隐含的指针形参,vs下面传递是通过ecx寄存器传递的,这样this访问变量的时候可以提高效率,不过这些优化取决于编译器,
关于this指针的存储位置
- 栈区,因为他是一个形参
用this指针证明类对象的存储方式
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << "Print()" << endl;
//cout << this << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print(); //正常运行
return 0;
}
- 这段代码不会发生崩溃,编译报错的情况,它是会正常运行的
- p->Print如果对p进行了解引用,就会报错,但这里是正常运行的,可见类对象的存储方式是猜测三:只保存成员变量,成员函数存放在公共的代码段
#include<iostream>
using namespace std;
class A
{
public:
void Print(int x)
{
this->_a = x;
cout << this->_a << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print(1); //崩溃
/*A m;
m.Print(1);*/
return 0;
}
- 这段代码会崩溃,空指针没有问题,但是对空指针进行接引用就会有问题
边栏推荐
猜你喜欢
(26)Blender源码分析之顶层菜单的关于菜单
One line of code to solve CoreData managed object properties change in SwiftUI problem of animation effects
Mysql environment installation under Linux (centos)
【云驻共创】【HCSD大咖直播】亲授大厂面试秘诀
The difference between adding or not adding the ref keyword when a variable of reference type is used as a parameter in a method call in C#
Shell常用脚本:Nexus批量上传本地仓库脚本
cobaltstrike
景区手绘地图的绘制流程
【MATLAB项目实战】LDPC-BP信道编码
Document management and tools in the development process
随机推荐
浏览器下载快捷方式到桌面(PWA)
MySQL数据库‘反斜杠\’ ,‘单引号‘’,‘双引号“’,‘null’无法存储
标段参数说明
vim的基本使用概念
leetcode:126. 单词接龙 II
What is customer profile management?
Interview Question: Implementing Deadlocks
hboot and recovery, boot.img, system.img
编译型语言和解释型语言的区别
SQL injection Less47 (error injection) and Less49 (time blind injection)
(26)Blender源码分析之顶层菜单的关于菜单
编程语言是什么
什么是客户画像管理?
(26) About menu of the top menu of Blender source code analysis
Dry goods | 10 tips for MySQL add, delete, change query performance optimization
Difference between first and take(1) operators in NgRx
To help the construction of digital government, the three parties of China Science and Technology build a domain name security system
SQL注入 Less47(报错注入) 和Less49(时间盲注)
Shell common script: Nexus batch upload local warehouse script
SQL注入 Less42(POST型堆叠注入)