当前位置: 首页 > ops >正文

C++类继承学习笔记

继承权限控制:

        继承权限分为public, protected, private,会修改基类的属性、成员在派生类的访问权限控制,对于基类的public、protected属性、成员,可以使用using声明来修改其访问权限控制

#include <iostream>
using namespace std;
class Base{
public:int property_public{};
protected:int property_protected{};
private:int property_private{};
};class Derived_public:public Base {
public:void func_test(){cout << property_public << endl;cout << property_protected << endl;//cout << property_private << endl;//报错,不可访问}
};class Derived_protected:protected Base{
public:void func_test(){cout << property_public << endl;cout << property_protected << endl;//cout << property_private << endl;//报错,不可访问}
};class Derived_private: private Base{
public:void func_test(){cout << property_public << endl;cout << property_protected << endl;//cout << property_private << endl;//报错,不可访问}
};
class Derived_protected_using:protected Base{
public:using Base::property_protected; //转为public属性
private:using Base::property_public;//转为private属性
};
int main(){Derived_public derived_public;cout << derived_public.property_public << endl;//cout << derived_public.property_protected << endl;// 报错 protected成员对外界不可访问Derived_protected derived_protected;//cout << derived_protected.property_public << endl;//报错 protected成员对外界不可访问Derived_protected_using derived_protected_using;cout << derived_protected_using.property_protected << endl;//可以,已经通过using转为publiccout << derived_protected_using.property_public << endl;//报错,已通过using转为private
}

 继承的构造函数与析构函数调用:

 普通继承:

先调用最基类的构造函数,再调用类属性的构造函数,最后调用自身构造函数

析构函数与构造函数的调用顺序相反

#include <iostream>
using namespace std;
class Base1{
public:Base1(){cout << "Base1 is constructed" << endl;}~Base1(){cout << "Base1 is destroyed" << endl;}
};class Base2:public Base1{
public:Base2(){cout << "Base2 is constructed" << endl;}~Base2(){cout << "Base2 is destroyed" <<endl;}
};class Property{
public:Property(){cout << "Property is constructed" << endl;}~Property(){cout << "Property is destroyed" << endl;}
};class Derived:public Base2{
public:Property p{};Derived(){cout << "Derived is constructed" << endl;}~Derived(){cout << "Derived is destroyed" << endl;}
};int main(){Derived d{};return 0;
}

输出:

Base1 is constructed
Base2 is constructed
Property is constructed
Derived is constructed
Derived is destroyed
Property is destroyed
Base2 is destroyed
Base1 is destroyed

继承多个基类:

按顺序调用基类的构造函数,最后调用自身的构造函数

析构顺序与构造相反

//修改Derived继承方式
//同时取消Base2对Base1的继承
class Derived:public Base2,public Base1{
public:Property p{};Derived(){cout << "Derived is constructed" << endl;}~Derived(){cout << "Derived is destroyed" << endl;}
};

输出:

Base2 is constructed
Base1 is constructed
Property is constructed
Derived is constructed
Derived is destroyed
Property is destroyed
Base1 is destroyed
Base2 is destroyed

虚继承与普通继承混合:

优先调用虚继承的基类构造函数,再按顺序调用普通继承的

析构顺序与构造相反

//再修改Derived继承方式
class Derived:public Base1,virtual public Base2{
public:Property p{};Derived(){cout << "Derived is constructed" << endl;}~Derived(){cout << "Derived is destroyed" << endl;}
};

输出:

Base2 is constructed
Base1 is constructed
Property is constructed
Derived is constructed
Derived is destroyed
Property is destroyed
Base1 is destroyed
Base2 is destroyed

全是普通继承,但是基类中有虚基类(该类虚继承过别的基类):

优先调用虚继承的基类,之后再按顺序调用普通继承的调用函数

析构与构造顺序相反

//添加Base3和Base4
class Base3:virtual public Base1{
public:Base3(){cout << "Base3 is constructed" << endl;}~Base3(){cout << "Base3 is destroyed" << endl;}
};
class Base4:virtual public Base2{
public:Base4(){cout << "Base4 is constructed" << endl;}~Base4(){cout << "Base4 is destroyed" << endl;}
};//修改Derived继承方式
class Derived:public Property,public Base3,public Base4{
public:Derived(){cout << "Derived is constructed" << endl;}~Derived(){cout << "Derived is destroyed" << endl;}
};

输出:

Base1 is constructed
Base2 is constructed
Property is constructed
Base3 is constructed
Base4 is constructed
Derived is constructed
Derived is destroyed
Base4 is destroyed
Base3 is destroyed
Property is destroyed
Base2 is destroyed
Base1 is destroyed

若调换Base3和Base4的继承顺序,那么Base1和Base2的构造顺序也调换

若将Property修改为虚继承,则优先构造Property

菱形继承:

继承的类具有共同的虚基类

先构造共同的虚基类,且只构造一次,再构造非虚继承的基类

析构顺序与构造相反

#include <iostream>
using namespace std;class Grand{
public:int grand;Grand(int x):grand{x}{cout << "Grand" << endl;}
};class Base1:virtual public Grand{
public:int base1;Base1(int x,int y):Grand{x},base1{y}{cout << "Base1" << endl;}
};
class Base2:virtual public Grand{
public:int base2;Base2(int x,int y):Grand{x},base2{y}{cout << "Base2" << endl;}
};
class Derived:public Base1,public Base2{
public:int derived;Derived(int x,int y,int z,int j):Grand{x},Base1{y,y},Base2{z,z},derived{j}{cout << "Derived" << endl;}
};int main(){Derived d{1, 2, 3, 4};cout << d.grand << endl;//看看到底是1,2还是3return 0;
}

输出:

Grand
Base1
Base2
Derived
1

总结:

优先按顺序构造虚基类,再顺序构造非虚基类

类的继承的构造函数写法

这里只讲比较难写的类型

背景:父类具有private成员

#include <iostream>
using namespace std;class Base{
public:Base(int x,int y):base_public{x},base_private{y}{}Base(const Base& t):base_public{t.base_public},base_private{t.base_private}{}Base& operator=(const Base& t){if(this==&t) return *this;base_public = t.base_public;base_private = t.base_private;return *this;}
public:int base_public;
private:int base_private;
};
class Derived:public Base{
public:Derived(int x, int y, int z, int j);Derived(const Derived& t);Derived& operator=(const Derived&t);
public:int derived_public;
private:int derived_private;
};Derived::Derived(int x,int y,int z,int j):Base{x,y},derived_public{z},derived_private{j}{}

1.拷贝构造函数

使用static_cast向上转换来调用基类的构造函数

Derived::Derived(const Derived& t):Base{static_cast<const Base&>(t)},derived_public{t.derived_public},derived_private{t.derived_private}
{}

2.赋值运算符

显式调用基类的赋值运算符

Derived& Derived::operator=(const Derived& t){if(this==&t)*this;Base::operator=(static_cast<const Base &>(t));derived_public = t.derived_public;derived_private = t.derived_private;return *this;
}

http://www.xdnf.cn/news/4697.html

相关文章:

  • 【软件推荐——ScreenToGif】
  • flutter 资料收集
  • Unity基础学习(九)基本组件Transform
  • 土壤电导率传感器测定土壤溶液中的可溶盐离子 智慧农业指导作用
  • 如何使用原点回归方式35进行回原
  • RHEL8搭建FOU隧道
  • Mybatis解决以某个字段存在,批量更新,不存在批量插入(高效)(一)
  • 【QT】深入理解 Qt 中的对象树:机制、用途与最佳实践
  • 第十六届蓝桥杯大赛软件赛C/C++大学B组部分题解
  • Spring Boot 3 + Undertow 服务器优化配置
  • YOGA Air X ILL10(83CX)/YOGA 14 ILL10X(83LC)2025款恢复开箱状态原装出厂Win11系统OEM镜像
  • 【记录】HunyuanVideo 文生视频工作流
  • 数字孪生[IOC]常用10个技术栈(总括)
  • 数据库的进阶操作
  • OCCT中的布尔运算
  • 机器学习 数据集
  • 第二章 Logback的架构(三)
  • Docker 核心目录结构
  • React知识框架
  • 【开源版】likeshop上门家政系统PHP版全开源+uniapp前端
  • 【5G通信】redcap和bwp 随手记
  • 路由交换实验
  • 【总结3】
  • ADC和DAC
  • 普冉MS32C001单片机,国产32位单片机,芯片特性和功能介绍
  • 什么是文本相似对比算法,原理是什么
  • 《100天精通Python——基础篇 2025 第16天:异常处理与调试机制详解》
  • 【言语理解】片段阅读之细节判断(9)
  • C#生成二维码和条形码
  • 在c++中static用在全局和局部有什么区别