C++:基类与派生类对象之间的赋值兼容关系
4.5 基类与派生类对象之间的赋值兼容关系
在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量。
在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量。这种不同类型之间的自动转换,称为赋值兼容。在基类和派生类对象之间也存在有赋值兼容关系,基类和派生类对象之间的赋值兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来代替。因为,通过公有继承,除了构造函数和析构函数外,派生类保留了基类其他的所有的成员。那么,派生类就具有基类的全部功能,凡是基类能够实现的功能,公有派生类都能实现。我们可以将派生类对象的值赋给基类对象,在用到基类对象的时候可以用其子类对象代替。
例如,下面声明的两个类:
class Base{ //声明基类
...
};
class Derived:public Base{ //声明基类Base的公有派生类Derived
...
};
根据兼容规则,在基类Base的对象可以使用的任何地方,都可以用派生类Derived的对象来代替,
但只能使用从基类继承来的成员。具体表现在以下几个方面:
(1)派生类对象可以向基类对象赋值,即用派生类对象中从基类继承来的数据成员,逐个赋值给基类对象的数据成员。
例如:
Base b; //定义基类Base的对象b
Derived d; //定义基类Base的公有派生类Derived的对象d
b=d; //用派生类Derived的对象d对基类Base的对象b进行赋值
这样的赋值效果是:对象b中所有数据成员都将具有对象d中对应数据成员的值。
(2)派生类对象可以初始化基类对象的引用。例如:
Base b; //定义基类Base的对象b
Derived d; //定义基类Base的公有派生类Derived的对象d
Base &br=d; //定义基类Base的对象的引用br,并用派生类Derived的对象对其进行初始化
(3)派生类对象地址可以赋值给指向基类对象的指针。例如:
Derived d; //定义基类Base的公有派生类Derived的对象b
Base *bp=&d; //把派生类对象的地址&d赋值给指向基类的指针bp,也就是说使指向基类
//对象的指针bp也可以指向派生类对象d
(4)如果函数的形参是基类对象或基类对象的引用,在调用函数时可以将派生类对象作为实参。例如:
class Base{ //声明基类Base
public:
int i;
...
};
class Derived:public Base{ //声明Base的公有派生类Derived
...
};
void fun(Base &bb)
{
cout<<bb.i<<endl; //输出该引用所代表的对象的数据成员i
}
在调用函数fun时,可以用派生类Derived的对象d4作为实参:
fun(d4);
输出派生类Derived的对象d4赋值给基类数据成员i的值。
//基类与派生类对象之间的交换
#include<iostream>
using namespace std;
class Base{ //声明基类Base
public:
int i;
Base(int x) //基类Base的构造函数
{
i = x;
}
Base(const Base &b)
{
cout<<"Base Copyconstructor"<<endl;
}
void show() //成员函数
{
cout<<"i="<<i<<endl;
}
};
class Derived:public Base{ //声明基类Base的公有派生类Derived
public:
Derived(int x):Base(x) //派生类的构造函数
{}
Derived(const Derived &d):Base(d)
{
cout<<"Derived Copyconstructor"<<endl;
}
};
void fun(Base &bb) //普通函数,形参为基类对象的引用
{
cout<<bb.i<<endl;
}
int main()
{
Base b1(); //定义基类对象b1
b1.show();
Derived d1(); //定义派生类对象d1
b1=d1; //用派生类对象d1给基类对象b1赋值
b1.show(); Derived d2(); //定义派生类对象d2
Base &b2=d2; //用派生类对象d2来对基类对象的引用b2进行初始化
b2.show(); Derived d3(); //定义派生类对象d3
Base *b3=&d3; //把派生类对象的地址&d3赋值给指向基类对象的指针b3
b3->show(); Derived d4(); //定义派生类对象d4
fun(d4); //派生类对象d4作为函数fun的实参 Derived d6(d4);
return ;
} /*
程序运行结果如下:
Base 100
Base 11
Base 22
Base 33
44
Base Copyconstructor
Derived Copyconstructor
说明:
(1)声明为指向基类对象的指针可以指向它的公有派生类的对象,但不允许指向它的私有派生的对象。
例如:
class Base{
...
};
class Derived:private Base{
...
};
int main()
{
Base op1,*ptr; //定义基类Base的对象op1及其指向基类Base的指针ptr
Derived op2; //定义派生类Derived的对象op2
ptr = &op1; //将指针ptr指向基类Base对象op1
ptr = &op2; //错误,不允许将指向基类Base的指针ptr指向它的私有派生类对象op2
......
return ;
} (2)允许将一个声明为指向基类的指针指向其公有派生类的对象,但是不能将一个声明为指向派生类
对象的指针指向其基类的一个对象。
例如:
class Base{
...
};
class Derived:public Base{
...
};
int main()
{
Base obj1; //定义基类Base的对象obj1
Derived obj2,*ptr; //定义派生类Derived的对象obj2及其指向派生类对象的指针ptr
ptr = &obj2; //将指针ptr指向派生类Derived对象obj2
ptr = &op2; //错误,不允许将指向派生类Derived指针ptr指向它的基类Base对象obj1
......
return ;
}
C++:基类与派生类对象之间的赋值兼容关系的更多相关文章
- 详解C++中基类与派生类的转换以及虚基类
很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...
- (转) C++中基类和派生类之间的同名函数的重载问题
下面有关派生类与基类中存在同名函数 fn: class A { public: void fn() {} void fn(int a) {} }; class B : public A { publi ...
- C++基类和派生类之间的转换
本文讲解内容的前提是派生类继承基类的方式是公有继承,关键字public 以下程序为讲解用例. #include<iostream> using namespace std; class A ...
- c++,派生类对象可以对基类赋值,基类对派生类不可以赋值
派生类对象可以对基类对象赋值,赋值时属于派生类独有的部分就舍弃不用. #include <iostream> using namespace std; class DemoA { publ ...
- C++学习21 基类和派生类的赋值
在C/C++中,经常会发生数据类型转换,例如整型数据可以赋值给浮点型变量,在赋值之前,先把整型数据转换为浮点型:反过来,浮点型数据也可以赋值给整型变量. 数据类型转换的前提是,编译器知道如何对数据进行 ...
- OOP1(定义基类和派生类)
面向对象程序设计基于三个基本概念:数据抽象,继承和动态绑定 数据抽象是一种依赖于接口和实现分离的编程技术.继承和动态绑定对程序的编号有两方面的影响:一是我们可以更容易地定义与其它类相似但不完全相同的类 ...
- 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)
[源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...
- c++中基类与派生类中隐含的this指针的分析
先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...
- 基类和派生类--this
基类指针在程序运行的时候的确指向的是一个派生类的对象,但指针的类型仍然是基类指针.C++是一种强类型语言,因此不能用基类指针类型的指针直接调用派生类:而且,同一个类可能有多种不同的派生类,因此不知道实 ...
随机推荐
- java dom4j解析xml用到的几个方法
1. 读取并解析XML文档: SAXReader reader = new SAXReader(); Document document = reader.read(new File(fileName ...
- 每日一“酷”之Queue
Queue—线程安全的FIFO实现 作用:提供一个线程安全的FIFO实现 Queue模块提供了一个适用于多线程编程的先进先出(first-in,first-out)数据结构,可以用来在生产者和消费者线 ...
- UnitTest
using Bll; using Model; using Dal; using NUnit.Framework; using NUnit.Mocks; using System.ServiceMod ...
- Virtualbox中安装Openwrt
Virtualbox:https://www.virtualbox.org/wiki/DownloadsOpenwrt:http://downloads.openwrt.org/backfire/10 ...
- sql server2000中使用convert来取得datetime数据类型样式(全)
sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007-0 ...
- Converting Storyboard from iPhone to iPad
I found out a kind of solution: Duplicate your iPhone-Storyboard and rename it MainStoryboard_iPad.s ...
- Oracle 异常处理
1.什么是异常 在PL/SQL中的一个警告或错误的情形都可被称为异常.包括编译时错误(PLS)和运行时错误(ORA).一个异常通常包含一个错误代码和错误文本,分别指示异常的编号和具体错误信息. 异 ...
- 深入浅出百度地图API开发系列(1):前言
百度地图API目前在地图API领域越来越受到众多开发者的关注,许多应用都使用到了百度地图API服务,包括博主me,我自己使用做的是Javascript API,根据经验,我想整理出一份系列教程,如果能 ...
- Java多线程——<三>简单的线程执行:Executor
一.概述 按照<Java多线程——<一><二>>中所讲,我们要使用线程,目前都是显示的声明Thread,并调用其start()方法.多线程并行,明显我们需要声明多个 ...
- transparent 的新问题
http://msdn.microsoft.com/en-us/library/windows/desktop/bb172255(v=vs.85).aspx 人物透明 显示是纹理和白色混合 开始怀疑是 ...