关于类的封装继承多态的一个简单复习笔记

#include "iostream"
#include "string.h"
/************************类的封装**********************************/
//结构体默认是公有的,类默认是私有的
//私有类
class Student {
	int age; 
	char sex;
	double score;
public:
	//封装起来变量取值方法,对于c++由于有指针不需要这么做
	void setScore(double score) {
		this->score = score;
	}
};

//公有类,相当于struct
class Student1 {
public:
	int age1;
    char sex1;
    double score1;
      };


//通过指针访问私有成员,直接访问对象地址
class Student2 {
	int age2;
	char sex2;
	double score2;
};

/************************继承**********************************/
//第一个类wood,基类,父类
class wood {
	char name[20];
	int length;
public:
	wood(char* n, int len) {
		strcpy(name, n);
		length = len;
	}
	void show() {
		std::cout << "这是一根" << length << "长的" << name;
	}
};
//继承,子类继承类
//子类继承父类会自动拥有父类所有成员;
class desk:public wood {
public:
	//继承子类的构造函数
	desk(char*n, int len) :wood(n, len) {

	};
};

/************************多态**********************************/
//大学生,小学生,中学生都有学习功能,但是学习方式不同,这种不一样专业叫多态
/***************number1**********************/
class student {
public:
	student(){
	};
	void study() {
		std::cout << "学生学习!" << std::endl;
	};
};
//虽然都继承了基类,但是学习方式都一样
class CollegeStudent:public student {

};
class MiddleStudent:public student {

};
class PupilStudent:public student {

};

/***************number2**********************/
//描述不同学习具备不同特性用多态
//多态本质就是:函数重写:1.基类函数修饰为虚函数:virtual修饰;2.派生类重写这个函数
class student1 {
public:
	int n;                 
	student1() {
	};
	//基函数修饰为虚函数
	virtual void study1() {
		std::cout << "学生学习!" << std::endl;
	};
	//基函数修饰为虚函数
	virtual void nstudy1() {
		std::cout << "学生不学习!" << std::endl;
	};
};
//虽然都继承了基类,但是学习方式都一样
class CollegeStudent1 :public student1 {
public:
	//继承函数重写
    void study1() {
		std::cout << "大学生学习!" << std::endl;
	};
};
class MiddleStudent1 :public student1 {
public:
	//继承函数重写
	void study1() {
		std::cout << "中学生学习!" << std::endl;
	};
};
class PupilStudent1 :public student1 {
public:
	//继承函数重写
	void study1() {
		std::cout << "小学生学习!" << std::endl;
	};
};
/***************number3**********************/
//多态的指针实现
void use(student1* p) {
	p->study1();
}
/************************主函数**********************************/
int main()
{   

	/****************私有类***********************************/
   //会报错
	Student s;
	s.score1 = 99.99; //私有成员不能根据对象名访问(封装)
	//不会报错
	s.setScore(99.99); //封装起来的变量赋值方法,由于C++有指针,此方法一般不用
	/****************公有类**********************************/
	Student1 s1;
	s1.score1 = 99.99;
	/********************私有类指针*************************/
	//只要知道类里面数据怎么存储,就可以根据内存操作封装变量
	//指着中存着什么类型就要将类型强制转换为(什么*)然后进行操作;
	Student2 s2;
	int *p =(int *) &s2; //强制类型转化
	*p = 18; //此时age2里边的值变为18;
	p++;
	*(char *)p = 'X'; //此时sex2里边的值变为X;
	(char*)p++;
	*(double *)p = 88.88;//此时score2里边的值变为88.888;
	/********************指针*************************/
	int n = 10; //int类型的变量,n绑定4个字节的内存段
	int m = 20;
	&n;         //得到n的首地址
	int* p;     //定义一个变量:保存一个指针,这个指针是int类型变量的首地址
	p = &n;     //指针变量指向n
	*p ;        //解引用,根据地址查找内存段
	*p = 100;   //此时n=100;
	p -= 3;      //不同编译器不同,变量存在堆栈
	*p;          //此时输出的是m的值为20;
	*p = 200;    //std::cout<<m<<std::endl;此时输出的是m为200
    /************************继承************************************/
	wood w("yueji", 40);
	w.show();
	desk dd("zhuzi",60);
	dd.show();
	/************************多态**********************************/
	//所有学习方式都一样,体现不出差异性
	student ts;
	CollegeStudent cs;
	MiddleStudent  ms;
	PupilStudent   ps;
	ts.study();
	cs.study();
	ms.study();
	ps.study();
	//想要体现出差异性就用多态
	student1 ts1;
	CollegeStudent1 cs1;
	MiddleStudent1  ms1;
	PupilStudent1   ps1;
	ts1.study1();//打印出“学生学习”
	cs1.study1();//打印出“大学生学习”
	ms1.study1();//打印出“中学生学习”
	ps1.study1();//打印出“小学生学习”
	//多态指针实现
	use(&ts1);//打印出“学生学习”
	use(&cs1);//打印出“大学生学习”
	use(&ms1);//打印出“中学生学习”
	use(&ps1);//打印出“小学生学习”
	/***************多态底层实现:虚函数表*****************/
	//1.如果类中有虚函数,类的大小多出来4个字节
	std::cout << sizeof(student) << std::endl; //当没有有virtual时大小为4
	std::cout << sizeof(student1) << std::endl;//当有virtual时大小为8
	student1 s1;
	//将s1加入断点查看发现s1中存在一个_vfptr,就是一个指针变量,指向一个指针数组,所以叫虚函数表(数组)
    //对象指针指向虚函数,有几个虚函数就指向几个数组,一个数组放置一个虚函数(这个数组就叫做虚函数表)
	//如果不是虚函数不会保存到对象里边
	//2.这四个字节是一个指针变量
	//3.这个指针变量指向一个数组(虚函数表)
	//4.验证
	//s1指向了虚函数表,故s1中存放的是虚函数表中的首地址,*(&s1)就可以得到虚函数表的首地址,还需要强制类型转换
	std::cout << &s1 << std::endl;
	std::cout << "虚函数表的地址" << *((int*)&s1) << std::endl;//虚函数表的首地址拿到
	//再次解引用,从首地址中拿到虚函数表中的第一个元素
	int *p = (int*)*((int*)&s1);//拿到虚函数表首地址
	int *p1 = (int*)*((int*)*((int*)&s1));//拿到数组即虚函数表中的第一个元素
	//找出函数指针类型
	typedef void(*FUNC)();
	FUNC f = (FUNC)p1;
	f(); //输出学生学习

	p++;
	int* p2 = (int*)*p;//虚函数表中第二个元素地址
	FUNC f = (FUNC)p2;
	f(); //输出学生玩
	//继承过来的函数会将虚函数表同时继承过来,但是首地址不一样,因为函数重写
	//5.派生类继承基类,会继承基类虚函数表中的所有元素
	//6.如果派生类重写,会用重写的函数覆盖继承过来的虚函数表中元素
	CollegeStudent1 Co;



}

视频链接——https://v.qq.com/x/page/g0614pl00v5.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值