C++类间转换之dynamic_cast
当在C++的基类与派生类之间转换时,其多态性充分显现出来;
本次只讨论 dynamic_cast 的用法。
在查阅资料后发现百度百科关于 dynamic_cast (以及static_cast) 的代码说得十分清楚,摘抄如下(正所谓英雄不问出处):
#include"stdafx.h"
#include<iostream>
#include<stdlib.h>
using namespace std;
class Base
{
public:
virtual void f(){cout<<"Base::f"<<endl;}
void f1(){cout<<"Base::f1"<<endl;}
private:
double x;
double y;
};
class Derived:public Base
{
public:
virtual void f(){cout<<"Derived::f"<<endl;}
virtual void k(){cout<<"Derived::k"<<endl;}
private:
double z;
};
class Base1
{
public:
virtual void g(){cout<<"Base1::g"<<endl;}
void g1(){cout<<"Base1::g1"<<endl;}
};
class Derived1:public Base,public Base1
{
public:
virtual void f(){cout<<"Derived1::f"<<endl;}
virtual void h(){cout<<"Derived1::h"<<endl;}
};
void Test1()
{
//对于单继承,
//如果pD真的指向Derived,用dynamic_cast和static_cast效果相同
cout<<"-----------------Test1-----------------"<<endl;
Base* pD=new Derived;
Derived* pD1=dynamic_cast<Derived*>(pD);
pD1->f();
pD1->k();
pD1->f1();
Derived* pD2=static_cast<Derived*>(pD);
pD2->f();
pD2->k();
pD2->f1(); //但是如果pB不是真的指向Derived,则用dynamic_cast则返回NULL,能够更早的禁止error的发生,
//如果用static_cast虽然返回的不为NULL,但是运行时可能抛出exception。
/**/////Errorcode
//Base*pB=new Base();
//Derived*pD3=static_cast<Derived*>(pB);
//pD3->f();
//pD3->k();
//pD3->f1();
//Derived*pD4=dynamic_cast<Derived*>(pB);
//pD4->f();
//pD4->k();
//pD4->f1();
}
void Test2()
{
//对于多重继承,
//如果pD真的指向的是Derived1,使用dynamic_cast和static_cast都可以转化为Derived1,
//但是如果要转化为Base的兄弟类Base1,必须使用dynamic_cast,使用static_cast不能编译。
cout<<"-----------------Test2-----------------"<<endl;
Base* pD=new Derived1;
Derived1* pD1=dynamic_cast<Derived1*>(pD);
pD1->f();
pD1->h();
pD1->f1();
Base1* pB1=dynamic_cast<Base1*>(pD);
pB1->g();
Derived1* pD2=static_cast<Derived1*>(pD);
pD2->f();
pD1->h();
pD2->f1();
/**/////errorcannotcompiler
//Base1*pB2=static_cast<Base1*>(pD);
//pB2->g();
//当然对于pB不是真的指向Derived1,想要转化为Derived1或Base的兄弟类Base1,情况与Test1中的error情况相同。
} void Test3()
{
cout<<"-----------------Test3-----------------"<<endl;
Derived1* pD1=new Derived1;
Base1* pB1= pD1; //此时pB1可以访问g(),g1()
Base* pB = dynamic_cast<Base*>(pB1); //兄弟类之间的转换
pB->f(); //Base类f()被覆盖,访问的是Derive1类的f(),这一点有点像是“基类对象访问派生类的函数”
pB->f1();
} int _tmain(int argc,_TCHAR*argv[])
{
Test1();
Test2();
Test3();
system("Pause");
return 0 ;
}
其中Test3()所测试的功能Test2()中已有。
Test3()中基类对象指针pB在访问f()时,由于Base类f()被覆盖,所以访问的是Derive1类的f();
另外对于 static_cast 的用法,这里就不多说了,自己去查吧。
C++类间转换之dynamic_cast的更多相关文章
- C++提供的四种新式转换--const_cast dynamic_cast reinterpret_cast static_cast
关于强制类型转换的问题,许多书都讨论过,写的最具体的是C++之父的<C++的设计和演化>. 最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_c ...
- Java基础之8个基本类型及基本类型间转换
8种基本数据类型 Java语言有8种基本数据类型, 分别用于存储整数.浮点数.字符数据和布尔类型数据.需要注意的是: 现在所介绍的仅仅是基本数据类型,后续还会介绍很多非基本数据类型.基本数据类型如图 ...
- 详解C++中基类与派生类的转换以及虚基类
很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...
- DataTable与实体类互相转换
/// <summary> /// DataTable与实体类互相转换 /// </summary> /// <typeparam name="T"& ...
- UML(一) 类图及类间关系
原创文章,同步发自作者个人博客,http://www.jasongj.com/uml/class_diagram/ UML类图 UML类图介绍 在UML 2.*的13种图形中,类图是使用频率最高的UM ...
- 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)
[源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...
- 图像二值化----otsu(最大类间方差法、大津算法)
最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津 法,简称OTSU.它是按图像的灰度特性,将图像分成背景和目标2部分.背景和目标之间的类间方差越大,说明构成图像 ...
- 最大类间方差法(Otsu)
由Otsu(大津展之)于1978年提出的最大类间方差法,是引起较多关注的一种阈值选取方法.它是在判决分析或最小二乘原理的基础上推导出来的. 参考文献: [1] Otsu N. A threshold ...
- Java基础知识强化34:String类之String类的转换功能
1. String类的转换功能 String[] split(String regex)//将字符串变成字符串数组(字符串切割) byte[] getBytes()//将字符串变成字节数组 char[ ...
随机推荐
- Shiro 修改权限,刷新权限
shiro 访问鉴权:Realm AuthorizingRealm->doGetAuthorizationInfo doGetAuthorizationInfo protected abstra ...
- 微信 msg_sec_check接口PHP 调用
$checkContent = '要检测的内容'; $url = 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token='. $res[& ...
- 169.求众数 leetcode Javascript
给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在众数. 示例 1: 输入: [3,2,3] 输出: 3 ...
- python序列成员资格
可以用做登录操作,判断用户名密码是否正确! 代码示例: database = [ ['], ['], ['], ['] ] username = input("UserName: " ...
- lamp一键配置 --转自秋水
https://teddysun.com/lamp LAMP一键安装脚本 最后修改于:2015年11月08日 / 秋水逸冰 / 54,300 次围观 973 本脚本适用环境: 系统支持:CentOS/ ...
- Centos 关闭图形界面
查看/etc/inittab如下: # systemd uses 'targets' instead of runlevels. # by default, there are two main ta ...
- 机器学习实战第二章----KNN
tile的使用方法 tile(A,n)的功能是把A数组重复n次(可以在列方向,也可以在行方向) argsort()函数 argsort()函数返回的是数组中值从大到小的索引值 dict.get()函数 ...
- Java微笔记(8)
Java 中的包装类 Java 为每个基本数据类型都提供了一个包装类,这样就可以像操作对象那样来操作基本数据类型 基本类型和包装类之间的对应关系: 包装类主要提供了两大类方法: 将本类型和其他基本类型 ...
- StringBuilder、StringBuffer和String三者的联系和区别
String 类 String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间. String a = "a ...
- 【Linux笔记】GRUB配置与应用,启动故障分析解决。
一.GRUB启动位置 GRUB是现今大多数Linux系统采用的自举程序,这里先来看一下Linux的程序顺序: 执行顺序 动作 固件Firmware(CMOS/BIOS) → POST(Pwer ...