首页 > 编程语言 >【30】C++子类相关

【30】C++子类相关

时间:2024-10-28 14:46:49浏览次数:8  
标签:继承 子类 30 number C++ class 派生类 基类 public

子类型关系

什么是子类型

公有继承时,派生类的对象可以作为基类的对象处理,派生类是基类的子类型。

 

#include <iostream>

using namespace std;

class A {
public:
	A() {}
	~A() {}
	void kill() { cout << "A kill." << endl; }
};

class B : public A {
public:
	B(){}
	~B(){}
	void kill() { cout << "B kill." << endl; }
};

void test(A a) {
	a.kill();  //调用的是A类对象的kill方法
}

int main(void) {
	A a;
	B b;
	test(a);
	test(b);

	system("pause");
	return 0;
}

子类型关系具有单向传递性。

C类是B类的子类型 

B类是A类的子类型

子类型的作用

在需要父类对象的任何地方, 可以使用”公有派生”的子类的对象来替代,

从而可以使用相同的函数统一处理基类对象和公有派生类对象

即:形参为基类对象时,实参可以是派生类对象

#include <iostream>
#include <sstream>

using namespace std;

class Father {
public:
	void play() {
		cout << "KTV唱歌!" << endl;
	}
};

class Son : public Father {
public:
	void play() {
		cout << "今晚吃鸡!" << endl;
	}
};


void party(Father *f1, Father *f2) {
	f1->play();
	f2->play();
}

int main(void) {
	Father yangKang;
	Son yangGuo;

	party(&yangKang, &yangGuo);

	system("pause");
	return 0;
}

执行:

KTV唱歌!

KTV唱歌!

注意:如果把Son改为protected继承,或private继承,就会导致编译失败!

子类型的应用 

1.基类(父类)的指针,可以指向这个类的公有派生类(子类型)对象。

Son yangGuo;

Father * f = &yangGuo;

2.公有派生类(子类型)的对象可以初始化基类的引用

Son yangGuo;

Father &f2 = yangGuo;

3.公有派生类的对象可以赋值给基类的对象

Son yangGuo;

Father f1 = yangGuo;

注意:以上的应用,反过来就会编译失败!

 

多重继承

什么是多重继承 

多继承/多重继承:

一个派生类可以有两个或多个基类(父类)。

多重继承在中小型项目中较少使用,在Java、C#等语言中直接取消多继承, 以避免复杂性.

 多重继承的用法

将多个基类用逗号隔开.

实例:

例如已声明了类A、类B和类C,那么可以这样来声明派生类D:

class D: public A, private B, protected C{
    //类D自己新增加的成员
};

D 是多继承形式的派生类,

D 有3个父类(基类)

它以公有的方式继承 A 类,

以私有的方式继承 B 类,

以保护的方式继承 C 类。

D 根据不同的继承方式获取 A、B、C 中的成员.

多继承的构造函数

多继承形式下的构造函数和单继承形式基本相同.

以上面的 A、B、C、D 类为例,D 类构造函数的写法为:

D(形参列表): A(实参列表), B(实参列表), C(实参列表){
    //其他操作
}

多继承的构造函数的调用顺序:

基类构造函数的调用顺序和和它们在派生类构造函数中出现的顺序无关,而是和声明派生类时基类出现的顺序相同。

多重继承的弊端: 二义性

// 解决多重继承的二义性的方法1:
	// 使用 "类名::" 进行指定, 指定调用从哪个基类继承的方法!
    wsc.Father::dance();
	wsc.Mother::dance();

	// 解决多重继承的二义性的方法2:
	// 在子类中重新实现这个同名方法, 并在这个方法内部, 使用基类名进行限定, 
// 来调用对应的基类方法
	wsc.dance();

 虚基类

问题

#include <iostream>	
#include <string>
#include <Windows.h>

using namespace std;

// 电话类
class Tel {
public:
	Tel() {
		this->number = "未知";
	}
protected:
	string number; //电话号码;
};

// 座机类
class FixedLine : public Tel {

};

// 手机类
class MobilePhone :public Tel {

};

// 无线座机
class WirelessTel :public FixedLine, public MobilePhone {
public:
	void setNumber(const char *number) {
		//this->number = number;   //错误, 指定不明确
		this->FixedLine::number = number;  //this可以省略
	}
	string getNumber() {
		//return MobilePhone::number;
		return MobilePhone::number;
	}
};

int main(void) {
	WirelessTel phone;
	phone.setNumber("13243879166");
	cout << phone.getNumber() << endl;  //打印未知
	system("pause");
	return 0;
}

输出:未知

解决

#include <iostream>	
#include <string>
#include <Windows.h>

using namespace std;

// 电话类
class Tel {   //虚基类
public:
	Tel() {
		this->number = "未知";
	}
protected:
	string number; //电话号码;
};

// 座机类
class FixedLine : virtual public Tel {  //虚继承

};

// 手机类
class MobilePhone : virtual public Tel { //虚继承

};

// 无线座机
class WirelessTel :public FixedLine, public MobilePhone {
public:
	void setNumber(const char *number) {
		this->number = number;  //直接访问number
	}
	string getNumber() {
		return this->number;   //直接访问number
	}
};

int main(void) {
	WirelessTel phone;
	phone.setNumber("13243879166");
	cout << phone.getNumber() << endl;
	system("pause");
	return 0;
}

输出:13243879166

常见错误总结

默认访问权限和语法要求

默认访问权限是private

访问权限之后一定要加冒号:

指定为某种访问权限之后, 就一直是这种权限, 除非再次指定为其他权限.

类的成员的访问权限, 与继承方式的区别

相同点:都有public,  private, protected

不同点:意义完全不同。

小结:

成员的访问权限:

public,  可以通过外部来访问(通过对象直接访问), 类似于C语言结构体中的成员

private, 只能在内部访问(在这个类的成员函数内访问),但是在子类的内部不能直接访问。

protected, 只能在内部访问,而且可以在子类的内部直接访问。

继承方式:

public, 父类成员, 被继承到子类后,访问权限都不变。

private, 父类成员, 被继承到子类后,访问权限都变为private

protected, 父类成员, 被继承到子类后,public权限的成员,降级为protected, 其他不变。

标签:继承,子类,30,number,C++,class,派生类,基类,public
From: https://blog.csdn.net/m0_57667919/article/details/143181709

相关文章

  • C++之OpenCV入门到提高001:使用 Visual Studio2022 配置 OpenCV 环境
    一、介绍从今天开始,我们又要开始一个新的系列了,这个系列就是《C++之Opencv入门到提高》。这个系列是有关如何使用C++语言,通过Opencv来实现图像处理、缺陷检测、视频处理、机器学习等功能。OpenCV我也是新接触的,一步一步的学习,一步一步提高。这个系列是以C++为基......
  • 异常:找不到模块“@/views/HouseDetail.vue”或其相应的类型声明。ts(2307)
    原因:在配置Vue项目路由,特别是使用TS时,可能会遇到模块声明错误。为了解决‘找不到模块’的ts(2307)错误,可以在src目录下创建vite-env.d.ts文件,然后引入特定代码来声明*.vue文件为Vue组件,允许通过import导入。这样通常能解决无法识别模块的问题。解决:在src目录下创建vite-env.d.ts......
  • 【原创】dell戴尔笔记本充电头4530改装typeC口过程记录笔记本电源改装c口三路接线定义
    在淘宝淘一个备用笔记本电脑,要求便携能用,最重要便宜(如果不便宜买了就想高价卖了)选择了xps13L322x,键盘屏幕有瑕疵,打折下来价格170左右,换了个键盘20。整体重量1.3kg左右,大小A4纸长一厘米。i73517u双核能到2.8Ghz,运行一两个软件够用。xps背光键盘舒服合理,有独立insert键,方便使用s......
  • C++在实际项目中的应用第二节:C++与区块链
    第五章:C++在实际项目中的应用第二课:C++与区块链区块链技术因其去中心化、不可篡改和透明性而受到广泛关注。在这门课程中,我们将深入探讨区块链的基本原理、智能合约的开发以及实际应用的案例分析,重点使用C++作为实现语言,以便充分发挥其高效性和强大的功能。1.区块链的......
  • Qt/C++地图雷达扫描/动态扇形区域/标记线实时移动/轮船货轮动态轨迹/雷达模拟/跟随地
    一、前言说明地图雷达扫描的需求场景也不少,很多人的做法是直接搞个覆盖层widget,在widget上绘制雷达,优缺点很明显,优点是性能高,毕竟直接在widget上绘制性能明显比js中绘制要高,缺点是要么动态计算经纬度坐标转屏幕坐标来实现跟随,要么固定的通过改变绘制的范围内容来跟随,但是总归使用......
  • C++学习,标准库 <cstdlib>
    <cstdlib> 是C++标准库中的一个头文件,提供了各种通用工具函数,包括内存分配、进程控制、环境查询、排序和搜索、数学转换、伪随机数生成等。这些函数最初来自C标准库 <stdlib.h>,在C++中进行了标准化和扩展。字符串转换函数calloc():分配指定数量和大小的内存空间,并将其......
  • 【C/C++】2.函数传入复杂类型实例时,传入值参数和引用参数的区别
    1.值参数传递(PassbyValue)原理:传入参数时会拷贝一份对象副本。优点:副本在函数内部可随意修改,不会影响原始数据。缺点:对于复杂类型,拷贝对象会消耗更多内存和性能。适用场景:函数只需读取少量数据,且无需修改原对象时,可以考虑值传递。voidprocessData(MyClassobj){......
  • 20222304 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    实验内容1.1实践内容正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧使用msfvenom生成jar、apk等其他文件使用veil加壳工具使用C+shellcode进行编程通过组合应用各种技术实现恶意代码免杀用另一电脑实测,在杀软开启的情况下,可运行并回连成功,注明电......
  • C++数据类型
    数据类型C++规定在创建一个变量或常量时,必须要指定出相应的数据类型,否则无法给变量分配内存。一、整型作用:整型变量表示的是整数类型的数据。语法:数据类型  变量名=变量初始值;        int  a=10;数据类型存在的意义:给变量分配合适的内存空间......
  • 实验二 c++
    实验任务一源代码t.h1#pragmaonce23#include<string>45//类T:声明6classT{7//对象属性、方法8public:9T(intx=0,inty=0);//普通构造函数10T(constT&t);//复制构造函数11T(T&&t);//移动构造函数12......