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. 修改UI中的值,无反应解决办法

    var targetObj = $("<input name='mydate' class='easyui-datebox'>").appendTo("#id ...

  2. django 更新model

    修改models.py 中对应的class 在admin.py 中 增加 admin.site.register(WafDevice) 进入dbshell python manage.py dbshe ...

  3. mysqldump 参数说明

    mysqldump参数说明 --all-databases , -A 导出全部数据库. mysqldump -uroot -p --all-databases --all-tablespaces , ...

  4. 显示 mac 隐藏文件

    显示Mac隐藏文件的命令:defaults write com.apple.finder AppleShowAllFiles -bool true 隐藏Mac隐藏文件的命令:defaults writ ...

  5. DRLSE 水平集算法总结

    背景: Level Set方法是美国数学家Osher(加州大学洛杉矶分校)和Sethian(加州大学伯克利分校)合作提出的.后者因为对Level Set的贡献获得了去年美国数学会与工业应用数学会联合颁 ...

  6. Eclipse中的Web项目自动部署到Tomcat(转)

    转自:http://www.cnblogs.com/ywl925/p/3815173.html 问题: 这里就有个问题,是怎么把Eclipse中的网站项目自动部署到tomcat中.在Eclipse中做 ...

  7. 【转载】CCombobox使用大全

    一.如何添加/删除Combo Box内容 1. 在Combo Box控件属性的Data标签里面添加,一行表示Combo Box下拉列表中的一行.换行用ctrl+回车. 2. 在程序初始化时动态添加 如 ...

  8. JQuery绑定和注销事件

    $('#action_list > li').each(function(){ $(this).unbind('click') .bind('click', function(){ /** so ...

  9. MSAA

    多重采样抗锯齿(MultiSampling Anti-Aliasing,簡稱MSAA)是一种特殊的超级采样抗锯齿(SSAA).MSAA首先来自于OpenGL.具体是MSAA只对Z缓存(Z-Buffer ...

  10. EBP的妙用[无法使用ESP定律时]

    1.了解EBP寄存器 在寄存器里面有很多寄存器虽然他们的功能和使用没有任何的区别,但是在长期的编程和使用 中,在程序员习惯中已经默认的给每个寄存器赋上了特殊的含义,比如:EAX一般用来做返回值,ECX ...