第十九章 19.2.1节练习
来源:互联网 发布:vb中chr 编辑:程序博客网 时间:2024/05/05 19:12
练习19.3
已知存在如下的类继承体系,其中每个类分别定义了一个公有的默认构造函数和一个虚析构函数:
class A{/* ... */};
class B : public A{/*...*/};
class C : public B{/*...*/};
class D : public B, public A{/*...*/};
下面的哪个dynamic_cast将失败?
(a) A *pa = new C;
B *pb = dynamic_cast< B* >(pa);
(b) B *pb = new B;
C *pc = dynamic_cast< C* >(pb);
(c) A *pa = new D;
B *pb = dynamic_cast< B* >(pa);
解答:
感谢asjdhs同学的提醒(详见评论),之前的代码的确有一些问题。
这里需要注意的是”注意转换指针的时候不会抛异常,只有在转引用的时候才会抛异常“。
更新如下:
测试代码如下:
#include <iostream>using namespace std;class A{public:A() = default;virtual ~A(){}};class B : public A{public:B() = default;virtual ~B(){}};class C : public B{public:C() = default;virtual ~C(){}};class D : public B, public A{public:D() = default;virtual ~D(){}};#define choose 1int main(){#if choose == 1 A *pa = new C; B *pb = dynamic_cast<B*>(pa); cout << "a's result: pb's address is " << static_cast<void*>(pb) << endl;#elif choose == 2 B *pb = new B; C *pc = dynamic_cast<C*>(pb); cout << "b's result: pc's address is " << static_cast<void*>(pc) << endl;#else A *pa = new D; B *pb = dynamic_cast<B*>(pa); cout << "c's result: pb's address is " << static_cast<void*>(pb) << endl;#endif}
这里我们将编译器换为clang3.4。
这里使用宏choose的原因是为了分开不同的小题(因为不同的题会在runtime和compiling-time有问题)
a) 当choose为1时,转换是没有问题的,你会在终端或命令行窗口中看到指针指向的地址。
b) 当choose为2时,转换就会出问题了,这个时候你会在命令行或终端窗口中看到指针指向的地址为0。这是C++在运行时对类型的检查。
这里原因可以参见MSDN(https://msdn.microsoft.com/en-us/library/cby9kycs.aspx)的 dynamic_cast_3.cpp上的解释。
c) 当choose为其他值时,编译都会出问题。我们来看看clang和gcc给出的错误信息:
clang3.4
test.cc:42:11: error: ambiguous conversion from derived class 'D' to base class 'A': class D -> class B -> class A class D -> class A A *pa = new D; ^~~~~1 error generated.
gcc4.9.2
test.cc:42:15: error: ‘A’ is an ambiguous base of ‘D’ A *pa = new D; ^
这里gcc的提示很简练,clang的提示很丰富。要表达的意思都是一个,因为这里使用到了多重继承,所以这里转换有二义性。
这里有疑问的是从那种继承方式往A进行转换(如同clang给出的提示那样)。
MSDN(上面网址)的 dynamic_cast_5.cpp上的解释,大家可以参考。
练习19.4
使用上一个练习定义的类改写下面的代码,将表达式*pa转换成类型C&:
if(C *pc = dynamic_cast< C* >(pa)){
// 使用C的成员
} else {
// 使用A的成员
}
解答:
我的理解如下:
int main(){A *pa = new C;try{C &pc = dynamic_cast<C&>(*pa);}catch (bad_cast &e){cout << e.what() << endl;}}
练习19.5
在什么情况下你应该使用dynamic_cast替代虚函数?
解答:
【引用】我们想使用基类对象指针或引用执行某个派生类操作并且该操作不是虚函数。
- 第十九章 19.2.1节练习
- 第十九章 19.2.2节练习
- 第十九章 19.2.4节练习
- 第十九章 19.1.1节练习
- 第十九章 19.4.1节练习
- 第十九章 19.4.2节练习
- 第十九章 19.4.3节练习
- 第十九章 19.5节练习 & 19.6节练习 & 19.8节练习
- 第十九章,指针小练习(C++)
- c++primer第五版第十九章练习
- <<快学Scala>> 第十九章 练习8 答案
- 第十九章
- php学习 第十九节
- 第十九节,Module
- 第十九节:下载文件
- 第十九章 映射
- 第十九章 将来时态
- 梦里人第十九章
- Leetcode ump Game II
- QWebKit对Html文件的解析
- 面霸不容易--且面且珍惜
- Building a Production Machine Learning Infrastructure
- OpenCV中Mat数据结构的用法
- 第十九章 19.2.1节练习
- Ubuntu 12.04 LTS 中文输入法的安装
- [matlab]根升余弦滤波器
- C++实现String类
- ubuntu 安装jdk1.7
- 红黑树和AVL平衡树的区别
- Linux中fork()函数详解
- Discover Feature Engineering, How to Engineer Features and How to Get Good at It
- 使用GPIO模拟I2C总线进行通信