四.struct和class的区别
我们知道struct是C语言中定义结构体的关键字,calss是C++中创建类的关键字,那么他俩到底有什么区别呢?我们通过一个例子来观察:
#include <stdio.h> struct Base{ int a; int b; int c; int d; }; void Test(){ Base t; t.a = 1; t.b = 2; t.c = 3; t.d = 4; } int main(){ Test(); return 0; }
我们先来通过struct关键字来定义,编译发现没有错误,那么我们再来通过class来创建一个类来观察一下:
#include <stdio.h> class Base{ int a; int b; int c; int d; }; void Test(){ Base t; t.a = 1; t.b = 2; t.c = 3; t.d = 4; } int main(){ Test(); return 0; }
这时候我们编译,发现出现了问题:编译器报错:cannot access private member declared in class 'Base'
并且报错四次,告诉我们不能访问Base中的成员a,b,c,d。而这样的报错,我们在前文中简介权限控制的时候就讲解过了。
那么我们就可以发现问题:我们用struct定义结构体的时候,它的成员权限默认为public,而我们calss创建类的时候,它的成员默认权限为private这就是struct和callss的区别。
五.private是否被继承
前文中我们提到:只有类中的成员才可以访问private变量或者函数,那么在继承的时候,private变量是否会继承呢?
我们首先通过观察类所占内存来分析是否继承:
#include <stdio.h> class Base{ private: int a; int b; public: int c; int d; }; class Sub:public Base{ int e; int f; }; void Test(){ Sub t; printf("%d",sizeof(Sub)); } int main(){ Test(); return 0; }
这里需要注意,我们继承的时候要在父类名前面加上public告诉编译器是共有类型,否则继承的父类变量全为private类型
我们在程序输出窗口可以看到输出了24
,说明Base类中不管是public类型还是private类型,都被继承过来了。
但是需要注意一点,继承过来的private类型,在子类中,无法使用,Base类中的private类型,只有Base类中的成员才可以调用
我们通过实例来论证:
#include <stdio.h> class Base{ private: int a; int b; public: int c; int d; }; class Sub:public Base{ public: int e; int f; }; void Test(){ Sub t; t.a = 1; t.b = 2; t.c = 3; t.d = 4; t.e = 5; t.f = 6; } int main(){ Test(); return 0; }
我们编译时,编译器错误提示:
说明继承过来的Base类中的a和b,不能在子类中使用。
六.类的继承中的构造函数
我们再来观察一个有趣的过程:
#include <stdio.h> class Base{ private: int a; int b; public: int c; int d; Base(){ printf("Base构造函数\n"); } }; class Sub:public Base{ public: int e; int f; Sub(int c,int d,int e,int f){ printf("Sub构造函数\n"); this->c = 1; this->d = 2; this->e = 3; this->f = 4; } }; void Test(){ Sub t(1,2,3,4); } int main(){ Test(); return 0; }
我们来到反汇编查看:
push 4 push 3 push 2 push 1 lea ecx,[ebp-18h] call @ILT+60(Sub::Sub) (00401041)
我们可以看到Sub的构造函数又调用了一个构造函数,我们跟进去看一下:
mov dword ptr [ebp-4],ecx mov ecx,dword ptr [ebp-4] call @ILT+65(Base::Base) (00401046)
我们看到程序输出窗口输出:
那么我们可以分析:当调用子类的构造函数时,父类的构造函数也会被调用,我们在上一节也讲解了,如果我们没有在类中定义构造函数,编译器会自动为我们编译一个无参构造函数。