C++ 权限控制,权限的继承

在前两章节中,我们学习了类的创建,封装,继承,构造函数和析构函数,其中很多都提到了权限,由于我们是从C语言过渡过来的,所以当时没有过多讲解,这一章节我们来讲解一下权限的控制和权限的继承。

一.类的创建规范

之前章节在创建类的时候,我们通常将构造函数定义在类成员中,由于这样可读性较差,所以我们需要将构造函数,析构函数的定义写在类中,将函数的实现定义在外部:
案例:

struct Base{
	int a;
	int b;

	Base();
	Base(int a,int b);
	!Base();
}; 

Base::Base(int a,int b){
	this->a = a;
	this->b = b;
}

**需要注意的是,在类外部写函数实现的时候,需要在前面加上类名和::,告诉编译器这是类中的函数,否则编译器不认识这到底是类中的函数还是你定义的新函数。

二.public和private

我们在上一章节链接: C++ 类,this指针中讲解过权限控制符的具体介绍,不了解的可以去看一下,由于protected不经常使用,所以我们这里只介绍public和private。
我们来看看这样一段程序:

#include <stdio.h>
struct Base{
public:
	int a;
	int b;
private:
	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类中的成员c和d。
那么这就很好地体现了C++中的权限控制:
1.对外提供的函数或变量,发布成public的,但是后续不能随意更改。
2.可能会变动的函数或者变量,定义为private,这样在使用的时候编译器会自动检测。
3.只有结构体内部的成员(构造函数,析构函数和变量)可以访问private成员。
4.public/private可以修饰函数,也可以修饰变量。

三.public成员真的不能访问吗

在上面的程序中我们明显看到是不能访问的,但是对于学习底层的我们来说,我们还是可以访问的,我们可以通过指针来访问:
比如说这段代码:

#include <stdio.h>
struct Base{
public:
	int a;
	int b;
	Base(int a,int b,int c,int d){
		this->a = a;
		this->b = b;
	}
private:
	int c;
	int d;
}; 


void Test(){
	Base t(1,2,3,4);
	int* p;
	p = (int*)&t;
	printf("%d\n",*p);
	printf("%d\n",*(p+1));
}
int main(){

	Test();

	return 0;
}

我们能看到函数输出窗口还是输出了a和b的值。所以说private的成员还是能访问的,但是我们要通过强制转化指针来访问。

四.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)

我们看到程序输出窗口输出:
程序输出
那么我们可以分析:当调用子类的构造函数时,父类的构造函数也会被调用,我们在上一节也讲解了,如果我们没有在类中定义构造函数,编译器会自动为我们编译一个无参构造函数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shad0w-2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值