C++ 底层分析 2.构造-析构,继承
2021/4/27 22:25:15
本文主要是介绍C++ 底层分析 2.构造-析构,继承,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
构造函数(初始)
- 与类同名
- 没有返回值
- 创建对象的时候执行
- 主要用于初始化
- 可以有好多个(最好有一个无参)
- 编译器不要求必须提供
重载:函数名字一样 参数个数或者类型不一样
析构函数(清理)
- 只能有一个析构函数,不能重载
- 不能带任何参数
- 不能带返回值
- 主要用于清理工作
- 编译器不要求必须提供
如下为析构函数和构造函数例子
struct Person { int age; int level; char* arr; //构造函数 Person(int age,int level) { this->age = age; this->level = level; arr = (char*)malloc(1024); } //重载构造函数 Person() { } //析构函数 ~Person() { printf("析构函数执行了"); free(arr); arr = NULL; } //成员函数 void Print() { printf("%d %d\n",age,level); } void Print(int x) { printf("%d %d\n",age,level); } }; int main() { Person p(1,2); return 0; }
继承
1.单继承
struct Person { int age; int sex; }; struct Teacher { int age; int sex; int level; int classId; }; struct Student { int age; int sex; int code; int score; }; Teacher t; 观察反汇编: t.age = 1; mov dword ptr [ebp-10h],1 t.sex = 2; mov dword ptr [ebp-0Ch],2 t.level = 3; mov dword ptr [ebp-8],3 t.classId = 4; mov dword ptr [ebp-4],4 push 10h printf("%d\n",sizeof(t)); push offset string "%d\n" (0042201c) call printf (004010e0) add esp,8 Student s; mov dword ptr [ebp-10h],1 mov dword ptr [ebp-0Ch],2 s.age = 1; mov dword ptr [ebp-8],3 s.sex = 2; mov dword ptr [ebp-4],4 s.code = 3; push 10h s.score = 4; push offset string "%d\n" (0042201c) call printf (004010e0) printf("%d\n",sizeof(s)); add esp,8 2、改变写法: struct Person { int age; int sex; }; struct Teacher:Person { int level; int classId; }; struct Student:Person { int code; int score; }; 观察反汇编: Teacher t; mov dword ptr [ebp-10h],1 mov dword ptr [ebp-0Ch],2 t.age = 1; mov dword ptr [ebp-8],3 t.sex = 2; mov dword ptr [ebp-4],4 t.level = 3; push 10h t.classId = 4; push offset string "%d\n" (0042201c) call printf (004010e0) printf("%d\n",sizeof(t)); add esp,8 Student s; mov dword ptr [ebp-10h],1 mov dword ptr [ebp-0Ch],2 s.age = 1; mov dword ptr [ebp-8],3 s.sex = 2; mov dword ptr [ebp-4],4 s.code = 3; push 10h s.score = 4; push offset string "%d\n" (0042201c) call printf (004010e0) printf("%d\n",sizeof(s)); add esp,8
变量是给编译器看的,对于底层来说,你取什么名字并没有什么意义
总结:
- 什么是继承?继承就是数据的复制
- 为什么要用继承?减少重复代码的编写
- Person 称为父类或者基类
- Teacher、Student称为子类或者派生类
- t和s可以称为对象或者实例.
- 可以用父类指针指向子类的对象.
图解:父类指针指向子类的对象.
2.多层继承
多层继承: 观察反汇编: struct X { int a; int b; }; struct Y:X { int c; int d; }; struct Z:Y { int e; int f; }; Z z; z.a = 1; mov dword ptr [ebp-18h],1 z.b = 2; mov dword ptr [ebp-14h],2 z.c = 3; mov dword ptr [ebp-10h],3 z.d = 4; mov dword ptr [ebp-0Ch],4 z.e = 5; mov dword ptr [ebp-8],5 z.f = 6; mov dword ptr [ebp-4],6 push 18h printf("%d\n",sizeof(z)); push offset string "%d\n" (0042201c) call printf (004010e0) add esp,8 struct X { int a; int b; }; struct Y:X { int a; int d; }; struct Z:Y { int e; int f; }; Z z; z.X::a = 1; mov dword ptr [ebp-18h],1 z.b = 2; mov dword ptr [ebp-14h],2 z.Y::a = 3; mov dword ptr [ebp-10h],3 z.d = 4; mov dword ptr [ebp-0Ch],4 z.e = 5; mov dword ptr [ebp-8],5 z.f = 6; mov dword ptr [ebp-4],6 push 18h push offset string "%d\n"(0042201c) call printf (004010e0) add esp,8 printf("%d\n",sizeof(z)); printf("%d\n",z.X::a); printf("%d\n",z.b); printf("%d\n",z.Y::a); printf("%d\n",z.d); printf("%d\n",z.e); printf("%d\n",z.f);
变量是给编译器看的,对于底层来说,你取什么名字并没有什么意义
有重名的成员,用::声明它属于哪个父类即可
3.多重继承
struct X { int a; int b; }; struct Y { int c; int d; }; struct Z:X,Y { int e; int f; }; Z z; 观察反汇编: z.a = 1; mov dword ptr [ebp-18h],1 z.b = 2; mov dword ptr [ebp-14h],2 z.c = 3; mov dword ptr [ebp-10h],3 z.d = 4; mov dword ptr [ebp-0Ch],4 z.e = 5; mov dword ptr [ebp-8],5 z.f = 6; mov dword ptr [ebp-4],6 printf("%d\n",sizeof(z)); push 18h push offset string "%d %x\n" (0042201c) call printf (004010e0) add esp,8
通过实验可以得出:一个子类可以有多个父类,即多重继承
对于重名的成员处理如上:
struct X { int a; int b; }; struct Y { int a; int d; }; struct Z:X,Y { int e; int f; }; 观察反汇编: Z z; mov dword ptr [ebp-18h],1 mov dword ptr [ebp-14h],2 z.X::a = 1; mov dword ptr [ebp-10h],3 z.b = 2; mov dword ptr [ebp-0Ch],4 z.Y::a = 3; mov dword ptr [ebp-8],5 z.d = 4; mov dword ptr [ebp-4],6 z.e = 5; push 18h z.f = 6; push offset string "%d %x\n" (0042201c) call printf (004010e0) printf("%d\n",sizeof(z)); add esp,8 printf("%d\n",z.X::a); printf("%d\n",z.b); printf("%d\n",z.Y::a); printf("%d\n",z.d); printf("%d\n",z.e); printf("%d\n",z.f);
内存示意图如下:
总结:
- 多重继承增加了程序的复杂度,容易出错
- 微软建议使用单继承,如果需要多重继承可以改为多层继承
- [ebp-4]为最后一个赋值
- TimeInfo timeinfo;若有继承,则先执行子构造函数再执行父构造函数
#include<cmath> #include<iostream> #include<iomanip> using namespace std; struct DateInfo { int year; int month; int day; DateInfo(int year,int month,int day) { this->year = year; this->month = month; this->day = day; cout<<"父类构造函数"<<endl; } DateInfo() { this->year = 2015; this->month = 4; this->day = 2; cout<<"父类构造函数"<<endl; } void SetDay(int day) { this->day = day; } int GetDay() { return this->day; } void SetMonth(int month) { this->month = month; } int GetMonth() { return this->month; } void SetYear(int year) { this->year = year; } int GetYear() { return this->year; } }; struct TimeInfo:DateInfo { int hour; int minute; int second; TimeInfo() { this->hour = 12; this->minute = 14; this->second = 0; cout<<"子类的构造函数"<<endl; } void SetHour() { this->hour = hour; } void SetMinute() { this->hour = hour; } void SetSecond() { this->second = second; } int GetHour() { return this->hour; } int GetMinute() { return this->minute; } int GetSecond() { return this->second; } }; void Test() { TimeInfo timeinfo; DateInfo* p = &timeinfo; p++; printf("%d",p->month); } int main() { Test(); return 0; }
题目:
#include<cmath> #include<iostream> #include<iomanip> using namespace std; struct MyString { char* arr; MyString(int Size) { this->arr = (char*)malloc(Size); memset(arr,0,Size); } MyString() { this->arr = (char*)malloc(1024); memset(arr,0,1024); } ~MyString() { free(arr); arr = NULL; } void SetString(char* str1) { memcpy(arr,str1,strlen(str1)); } void PrintString() { printf("%s\n",arr); } void AppendString(char* stradd) { char* pTemparr = this->arr; while(*++pTemparr); memcpy(pTemparr,stradd,strlen(stradd)); } int Size() { return strlen(arr); } }; void Test1() { MyString mystring(1000); mystring.SetString("哎Mikasys"); mystring.PrintString(); printf("%d\n",mystring.Size()); mystring.AppendString("爱你爱你"); mystring.PrintString(); printf("%d\n",mystring.Size()); } int main() { Test1(); return 0; }
这篇关于C++ 底层分析 2.构造-析构,继承的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-15PingCAP 黄东旭参与 CCF 秀湖会议,共探开源教育未来
- 2024-05-13PingCAP 戴涛:构建面向未来的金融核心系统
- 2024-05-09flutter3.x_macos桌面os实战
- 2024-05-09Rust中的并发性:Sync 和 Send Traits
- 2024-05-08使用Ollama和OpenWebUI在CPU上玩转Meta Llama3-8B
- 2024-05-08完工标准(DoD)与验收条件(AC)究竟有什么不同?
- 2024-05-084万 star 的 NocoDB 在 sealos 上一键起,轻松把数据库编程智能表格
- 2024-05-08Mac 版Stable Diffusion WebUI的安装
- 2024-05-08解锁CodeGeeX智能问答中3项独有的隐藏技能
- 2024-05-08RAG算法优化+新增代码仓库支持,CodeGeeX的@repo功能效果提升