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++:基类与派生类对象之间的赋值兼容关系的更多相关文章

  1. 详解C++中基类与派生类的转换以及虚基类

    很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...

  2. (转) C++中基类和派生类之间的同名函数的重载问题

    下面有关派生类与基类中存在同名函数 fn: class A { public: void fn() {} void fn(int a) {} }; class B : public A { publi ...

  3. C++基类和派生类之间的转换

    本文讲解内容的前提是派生类继承基类的方式是公有继承,关键字public 以下程序为讲解用例. #include<iostream> using namespace std; class A ...

  4. c++,派生类对象可以对基类赋值,基类对派生类不可以赋值

    派生类对象可以对基类对象赋值,赋值时属于派生类独有的部分就舍弃不用. #include <iostream> using namespace std; class DemoA { publ ...

  5. C++学习21 基类和派生类的赋值

    在C/C++中,经常会发生数据类型转换,例如整型数据可以赋值给浮点型变量,在赋值之前,先把整型数据转换为浮点型:反过来,浮点型数据也可以赋值给整型变量. 数据类型转换的前提是,编译器知道如何对数据进行 ...

  6. OOP1(定义基类和派生类)

    面向对象程序设计基于三个基本概念:数据抽象,继承和动态绑定 数据抽象是一种依赖于接口和实现分离的编程技术.继承和动态绑定对程序的编号有两方面的影响:一是我们可以更容易地定义与其它类相似但不完全相同的类 ...

  7. 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)

    [源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...

  8. c++中基类与派生类中隐含的this指针的分析

    先不要看结果,看一下你是否真正了解了this指针? #include<iostream> using namespace std; class Parent{ public: int x; ...

  9. 基类和派生类--this

    基类指针在程序运行的时候的确指向的是一个派生类的对象,但指针的类型仍然是基类指针.C++是一种强类型语言,因此不能用基类指针类型的指针直接调用派生类:而且,同一个类可能有多种不同的派生类,因此不知道实 ...

随机推荐

  1. Optimize date2str function

    /*************************************************** Created Date: 19 Jul 2013 Created By: Jimmy Xie ...

  2. IOS中Retain和Copy的区别

    1 ,可读性: readonly  . readwrite@property(readwrite,....) valueType value;这个属性是变量的默认属性,就是如果你 (readwrite ...

  3. (菜鸟要飞系列)五,基于Asp.Net MVC5的后台管理系统(添加数据表的分页功能)

    献上代码 ) { List<UserModel> arrayUserModel = new List<UserModel>(); string strText = Reques ...

  4. iTween基础之Audio(音量和音调的变化)

    一.基础介绍:二.基础属性 原文地址 : http://blog.csdn.net/dingkun520wy/article/details/50826033 一.基础介绍 AudioTo:改变声音的 ...

  5. 构件图 Component Diagram

    构件图是显示代码自身结构的实现级别的图表.构件图由诸如源代码文件.二进制代码文件.可执行文件或动态链接库 (DLL) 这样的构件构成,并通过依赖关系相连接 下面这张图介绍了构件图的基本内容: 下面这张 ...

  6. LoadRunner 学习笔记(3)基础

    LoadRunner包含的组件: Virtual User Generator 录制最终用户业务流程并创建自动化性能测试脚本,即 Vuser 脚本 Controller 组织.驱动.管理并监控负载测试 ...

  7. Java 8 VM GC Tuning Guide Charter3-4

    第三章 Generations One strength of the Java SE platform is that it shields the developer from the compl ...

  8. VS连接远程数据库,连接sqlserver2008,显示“基础提供程序在 Open 上失败”

    今天安装完成VS2012后,在调试2010的程序的时候,出现“基础提供程序在 Open 上失败”,于是用vs连接远程sql2008,才发现问题是:“已成功与服务器连接,但是登录前的握手期间发生错误”, ...

  9. Ubuntu 常用软件安装方法

    macubuntu 安裝方法: $wget https://github.com/downloads/ChinaLuo/Mac_Ubuntu/Mac_Ubuntu-12.04.tar.gz -O /t ...

  10. Smarty插件简单开发

    smarty的插件相当简单,你的网站经常会用到一些特定的Url或Controller或Action的路由地址的动态生成,通过smarty插件方式可以很轻松的实现. 在smarty/plugins目录下 ...