C++类型兼容规则

一、概念

类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代。通过公有继承,派生类得到了基类中除构造函数、析构函数之外的所有成员。这样,公有派生类实际就具备了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决。

再来看一下派生类中从基类中继承而来的成员和新增成员的关系:
在这里插入图片描述
虽然这个不是实际的物理模型,但是起码我们能大致明白两者的关系,同时也可以发现,派生类其实是可以被当作基类来使用的,因为它拥有基类的几乎所有成员(除了构造、析构函数)。
而实际上在基类与派生类之间存在一种转换,即派生类到基类类型转换。和其他类型转换一样,编译器会隐式地执行派生类到基类的转换
存在如下三种转换:
->>派生类的对象可以隐含转换为基类对象。
->>派生类的对象可以初始化基类的引用。
->>派生类的指针可以隐含转换为基类的指针。

二、代码

#include <iostream>
using namespace std;
class A {
	public:
		A() = default;
		A(int a1, int b1) : a(a1), b(b1) { }
		~A() { }
		void print1() const{cout << a << ' ' << b << endl;}
		int a = 0, b = 0;
};
class B : public A {
	public:
		B() = default;
		B(int a1, int b1, const string s1) : A(a1, b1), s(s1) { }
		B(B &item) {
			this->a = item.a;
			this->b = item.b;
			this->s = item.s;
		}
		~B() { }
		void print2() const{this->print1(); cout << s << endl;}
	private:
		string s = "abc";
};
void display1(A &item) {
	item.print1();
}
void display2(A *ptr) {
	ptr->print1();
}
int main() {
	A a1(1, 1);   
	B b1(1, 2, "def");      
	A a2(b1);   //基类的对象可以用来初始化派生类的对象
	display1(b1);   //参数类型为基类对象的函数同样也可以使用派生类的对象作为参数
	A &quote1 = b1;  //基类的引用可以绑定派生类对象
	A *ptr1 = &b1;   //基类的对象指针同样可以指向派生类对象的地址
	display2(ptr1);
	return 0;
}

该程序定义了两个类,基类A和派生类B。
然后还有两个函数display1和display2,两个函数的参数类型分别是基类对象的引用还有基类的对象指针。
在主函数中我们可以发现:
在这里插入图片描述

三、注意事项和总结

但是我们需要尤其注意的是,不存在从基类向派生类的隐式类型转换

A base;
B *ptr = &base;  //错误:不能将基类转换成派生类
B &quote = base; //错误:不能将基类转换成派生类

上述的两种转换都想从基类向派生类转换,是错误的。如果上述赋值是合法的,则我们有可能会使用ptr指针或者quote引用访问base中本不存在的成员。
除此之外:
在这里插入图片描述
类型兼容的好处是对于基类及其公有派生类的对象,可以使用相同的函数统一进行处理。因为当函数的形参为基类的对象(或引用、指针)时,实参可以是派生类的对象(或指针),而没有必要为每一个类设计单独的模块,大大提高了程序的效率。


笔记中大部分内容引用自《C++语言程序设计》和《C++ Primer》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值