C++编程 面向对象之继承思想 案例解析

目录

一:基类 派生类 继承中的内存占用

二:基类 派生类 继承中的执行顺序

三:基类的成员属性 使用protected修饰

四:面向对象程序设计 继承 源码示例

五:重定义


一:基类 派生类 继承中的内存占用

派生类内存占用 = 父类数据成员内存 + 自身特有成员内存;示例如下

#include<iostream>
using namespace std;
#include "CLabel.h"
#include"CEdit.h"
#include"CButton.h"
#include"CTools.h"
#include"CLogin.h"
#include"CtrBase.h"
#include"Father.h"
#include"Child.h"

int main()
{
	cout<<sizeof(CtrBase)<<endl;//36
  
	//派生类内存占用 父类数据成员内存+自身特有成员内存
	cout<<sizeof(CEdit)<<endl;//48
}

二:基类 派生类 继承中的执行顺序

继承过程中构造和析构的执行顺序:

基类构造 派生类构造 派生类析构 基类析构;示例如下

#include<iostream>
using namespace std;
#include "CLabel.h"
#include"CEdit.h"
#include"CButton.h"
#include"CTools.h"
#include"CLogin.h"
#include"CtrBase.h"
#include"Father.h"
#include"Child.h"

int main()
{
   	CEdit editName(34,10,10,3,"",8,2,1);
    //基类CtrBase带参构造函数
    //CEdit带参构造--派生类
    //派生类--CEdit析构函数
    //基类CtrBase析构函数
}

三:基类的成员属性 使用protected修饰

如下,子类不能调用父类的私有成员

//error C2248: 'startX' : cannot access protected member declared in class 'CtrBase'

#include<iostream>
using namespace std;
#include "CLabel.h"
#include"CEdit.h"
#include"CButton.h"
#include"CTools.h"
#include"CLogin.h"
#include"CtrBase.h"
#include"Father.h"
#include"Child.h"

int main()
{
   	CEdit editName(34,10,10,3,"",8,2,1);
	cout<<editName.startX<<endl;
//error C2248: 'startX' : cannot access protected member declared in class 'CtrBase'
}

通过在基类中为private修饰的成员属性 设计get方法,为子类提供访问接口,这样的操作不能体现出继承的优势性,

因此,对于基类的成员属性,使用protected修饰,子类可以直接访问 

四:面向对象程序设计 继承 源码示例

通过以下 父与子 的案例 【深入学习面向对象程序设计中的继承思想】 

Father.h:(基类 头文件)

#ifndef FATHER_H
#define  FATHER_H
#include<iostream>
using namespace std;

class Father
{
public:
	Father();
	~Father();
	void print();
	int pub;
	int getPublic();
	int getPrivate();//get方法类外访问
	int getProtected();
private:
	int num;
protected:
	int pro;
};

#endif

Father.cpp:(基类 源文件)

#include"Father.h"

Father::~Father()
{
	cout<<"父类的析构函数"<<endl;
}

Father::Father()
{
	this->num = 100;//private
	this->pro = 100;//protected
	this->pub = 100;//public
	cout<<"父类的构造函数"<<endl;
}

void Father::print()
{
	cout<<"父类print:private num="<<this->num<<endl;//private
}

int Father::getPublic()
{
	return this->pub;
}
int Father::getPrivate()
{
	return this->num;
}
int Father::getProtected()
{
	return this->pro;
}

Child.h:(派生类 头文件)

#ifndef CHILD_H
#define CHILD_H
#include"Father.h"

class Child : public Father
{
public:
	Child();
	~Child();
	void print();
	void speak();
	void change();
private:
	int num;    //继承自父类的成员变量
	int hobby;  //子类自身的成员变量
};

#endif

Child.cpp:(派生类 源文件)

下面代码中 父类中private修饰的成员属性,在子类获取不到,报错,注释掉即可(已注释)

#include"Child.h"

Child::~Child()
{
	cout<<"子类的析构函数"<<endl;
}

Child::Child()
{
	cout<<"子类的构造函数"<<endl;
}

//派生类重定义基类函数
//子类中有跟父类同名的函数 优先走子类
void Child::print()
{
	cout<<"子类根据自身特殊需求重定义父类的函数"<<endl;
}

void Child::speak()
{                                          //1.public公有继承
	cout<<"子类的成员特有函数"<<endl;
//	cout<<"private:"<<Father::num<<endl;   //父类private   子类获取不到
	cout<<"protected:"<<Father::pro<<endl; //父类protected 子类获取的到
	cout<<"public:"<<Father::pub<<endl;    //父类public    子类获取的到
//error C2248: 'num' : cannot access private member declared in class 'Father'
/*	父类的构造函数
    子类的构造函数
    子类的成员特有函数
    protected:100
    public:100
    子类的析构函数
    父类的析构函数*/
}

//子类成员内部无法访问private
void Child::change()
{
//	Father::num = 100;  //报错
	Father::pro = 100;
	Father::pub = 100;
}

get方法获取私有成员变量

在基类中为自己的私有的成员属性 设计get方法,提供类外访问的接口,子类就可以通过调用基类的get方法访问基类的私有成员属性(这样体现不出来继承的优势,因此,基类的成员属性若是要给派生类访问,使用protected修饰基类的成员属性即可)

void Child::speak()
{                                          //1.public公有继承
	cout<<"子类的成员特有函数"<<endl;
	cout<<"private:"<<Father::getPrivate()<<endl;  //get方法: 父类private 子类获取的到
	cout<<"protected:"<<Father::pro<<endl;         //         父类protected子类获取的到
	cout<<"public:"<<Father::pub<<endl;            //         父类public   子类获取的到
/*	父类的构造函数
    子类的构造函数
    子类的成员特有函数
    private:100
    protected:100
    public:100
    子类的析构函数
    父类的析构函数 */
}

main.cpp:(主入口测试)

#include<iostream>
using namespace std;
#include "CLabel.h"
#include"CEdit.h"
#include"CButton.h"
#include"CTools.h"
#include"CLogin.h"
#include"CtrBase.h"
#include"Father.h"
#include"Child.h"

int main()
{
   Child a;
   a.speak();
}

小结:基类【想要子类继承】的成员属性用protected修饰

#ifndef CTRBASE_H
#define CTRBASE_H
#define LABEL 1
#define EDIT 2
#define BUTTON 3

class CtrBase
{
public:
	CtrBase();
	~CtrBase();
	CtrBase(int x,int y,int w,int h,char *pcontent);
    void show();

protected:  //基类成员属性用protected修饰
	int startX;
	int startY;
	int width;
	int height;
	char content[20];  //内容
};

#endif

派生类继承基类的时候 一般使用 公有public继承  如下

class CLabel:public CtrBase  

子类可以继承父类所有成员属性(包括私有),只是父类private修饰的成员属性,子类访问不到,需要使用get方法来访问 (继承 & 访问 是不同的 子类可以继承父类所有 不代表 子类可以访问父类所有)

派生类继承基类的时候若是使用私有继承,子类仍然可以get set方法访问父类private成员属性;但是子类的子类就不能get set方法继续访问了

调用方式     

类名::(域运算符)       

对象.(点运算符)

五:重定义

派生类重定义基类函数

子类有和父类 函数原型完全一样 会优先走子类 ---》 重定义 

基类 函数原型和派生类一样  如下

void Father::print()
{
	cout<<"父类print:private num="<<this->num<<endl;//private
}

派生类 函数原型和基类一样 如下 

//派生类重定义基类函数
//子类中有跟父类同名的函数 优先走子类
void Child::print()
{
	cout<<"子类根据自身特殊需求重定义父类的函数"<<endl;
}

main.cpp 主入口测试 

#include<iostream>
using namespace std;
#include "CLabel.h"
#include"CEdit.h"
#include"CButton.h"
#include"CTools.h"
#include"CLogin.h"
#include"CtrBase.h"
#include"Father.h"
#include"Child.h"

int main()
{
   Child a;
   a.print();
   //父类的构造函数
   //子类的构造函数
   //子类根据自身特殊需求重定义父类的函数
   //子类的析构函数
   //父类的析构函数
}

由结果不难看出,派生类会隐藏基类的方法,走自己的方法 

小结:重定义函数的函数原型和基类中被重定义函数的函数原型必须完全相同

如:父与子都有void print(); 【函数原型完全一样】会导致基类的成员函数被隐藏,走子类的方法

什么时候重定义

当父类的函数里面的操作不足以满足子类,子类就可以写与父类函数类型相同的函数来进行重定义

重载和重定义:重载参数不一样 但 重定义整个函数声明都一样(整个函数原型都一致)

类指针 :

类也是一种数据类型

指针操作对象 用->运算符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chenruhan_QAQ_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值