基类与派生类对象之间的赋值兼容关系(C++ 学习笔记 35)

  • Post author:
  • Post category:其他


不同类型的数据之间的自动转换和赋值,称为

赋值兼容。


在基类和派生类对象之间也存在有赋值兼容关系,基类和派生类对象之间的

赋值兼容规则

是指在需要基类对象的任何地方,都可以使用

公有派生类的对象

来替代。

通过公有继承,派生类保留了基类中除构造函数、析构函数之外的所有成员,基类的公有或保护成员的访问权限在派生类中全部原样保留了下来,在派生类外可以调用基类的公有成员函数访问基类的私有成员。因此,公有派生类具有基类的全部功能,基类能够实现的功能,公有派生类都能实现。

class Base{
	··· ···
};
class Derived:public Base{
	··· ···
};

根据赋值兼容规则,在基类 Base 的对象可以使用的任何地方,都可以用派生类 Derived 的对象来替代,但只能使用从基类继承来的成员。具体体现在以下几个方面:


(1)派生类对象可以向基类对象赋值,

即用派生类对象中从基类继承来的数据成员逐个赋值给基类对象的数据成员。

Base b;			//定义基类 Base 的对象 b
Derived d;		//定义基类 Base 的公有派生类 Derived 的对象 d
b=d;			//用派生类 Derived 的对象 d 对基类对象 b 赋值


(2)派生类对象可以初始化基类对象的引用。

Base b;		//定义基类 Base 的对象 b
Derived d;		//定义基类 Base 的公有派生类 Derived 的对象 d
Base &br=d;		//定义基类 Base 的对象的引用 br,并用派生类 Derived 的对象 d 对其初始化


(3)派生类对象的地址可以赋给指向基类对象的指针。(最常见到)

Derived d;	//定义基类 Base 的公有派生类 Derived 的对象 d
Base *bp=&d;	//把派生类对象的地址 &d 赋值给指向基类的指针 bp,
				//即,使指向基类对象的指针 bp 也可以指向派生类对象 d


(4)如果函数的形参是基类对象或基类对象的引用,在调用函数时可以用派生类对象作为实参。

class Base{
	public:
		int i;
		··· ···
};
class Derived:public Base{		//定义基类 Base 的公有派生类 Derived
··· ···
};
void fun(Base &bb){		//普通函数,形参为基类 Base 对象的引用
	cout<<bb.i<<endl;		//输出该引用所代表的对象的数据成员 i
}

在调用函数 fun 时可以用派生类 Derived 的对象 d4 作为实参:

fun(d4)

输出派生类 Derived 的对象 d4 赋给基类数据成员 i 的值。



例 1:基类与派生类对象之间的转换
#include<iostream>
using namespace std;
class Base{		//声明基类 Base 
	public:
		int i;
		Base(int x){	//基类的构造函数 
			i=x;
		}
		void show(){	//成员函数 
			cout<<"Base "<<i<<endl;
		}
};
class Derived:public Base{		//声明公有派生类 Derived 
	public:
		Derived(int x):Base(x){		//派生类的构造函数 
		}
};
void fun(Base &bb){		//普通函数,形参为基类对象的引用 
	cout<<bb.i<<endl;
}
int main(){
	Base b1(100);	//定义基类对象 b1
	b1.show();
	Derived d1(11);		//定义派生类对象 d1
	b1=d1;		//用派生类对象 d1 给基类对象 b1 赋值
	b1.show();	 
	Derived d2(22);		//定义派生类对象 d2 
	Base &b2=d2;	//用派生类对象 d2 来初始化基类对象的引用 b2
	b2.show();
	Derived d3(33);		//定义派生类对象 d3
	Base *b3=&d3;		//把派生类对象的地址 &d3 赋值给指向基类的指针 b3
	b3->show();		
	Derived d4(44);		//定义派生类对象 d4
	fun(d4);		//派生类的对象 d4 作为函数 fun 的形参
	return 0; 
}

执行结果为:

在这里插入图片描述


说明:



(1)声明为基类对象的指针可以指向它的公有派生的对象,但不允许指向它的私有派生的对象。

class Base{
	··· ···
};
class Derived:private Base{  //定义私有派生类 Derived
	··· ···
};
int main(){
	Base op1,*ptr;		//定义基类 Base 的对象 op1 及指向基类 Base 的指针 ptr
	Derived op2;		//定义派生类 Derived 的对象 op2
	ptr = &op1;		//将指针 ptr 指向基类对象 op1
	ptr = &op2;		//错误,不允许将指向基类 Base 的指针 ptr 指向它的私有派生类对象op2
	···
}


(2)允许将一个声明为指向基类的指针指向其公有派生类的对象,但是不能将一个声明为指向派生类对象的指针指向其基类的一个对象。

class Base{
	··· ···
};
class Derived:public Base{
	··· ···
};
int main(){
	Base obj1;		//定义基类对象 obj1
	Derived obj2,*ptr;		//定义派生类对象 obj2 及指向派生类的指针 ptr
	ptr = &obj2;		//将指向派生类对象的指针 ptr 指向派生类对象 obj2
	ptr = &obj1;		//错误,将指向派生类对象的指针 ptr 指向其基类对象 obj1
}



版权声明:本文为aaqian1原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。