看完EffectiveC++的关于转型的章节,顿时认为周围的代码都处在悬崖边上~~

C的旧式转型:inta
= 10; double b = (double)a;

对于C++的四种转型函数,

const_cast去掉对象的常量性(仅仅此一个操作符有此功能!)

dynamic_cast一般用于继承体系中某对象的归属,耗费较大

reinterpret_cast低级转型,差点儿不用。

static_cast强迫隐式转换int->double,
void * ->typed *

在类的expecilit构造函数中,比如:

class Widget
{
public:
explicit: Widget(int size);
....
};

旧式转型有时也用,比方在,对于一个须要Widget对象作为參数的函数中,比如:voidf(
Widget &w ); 调用时,使用旧式转型f(Widget(15));

转型并不不过只告诉编译器将该对象视为什么类型,编译器会做出一些动作来完毕转型,比如:

将int转化为double,在完毕浮点数的乘法的时候,显然是要产生不同的目标码的。

以下的样例可能你每天都在用,那就是"基类的指针指向子类的对象",比如:

class Based { ... };

class Derived: public Based{ ... };

Derived de;

Based *pb = &de; //基类的指针指向子类的对象。

在实际。这两个指针的值可能不一样,也许是在当前对象上加了一个偏移量,这也就意味着,同一个Derived对象可能有两个地址,基类类型的指针与派生类类型的指针可能是不一样的。当然这依赖于内存布局(啊哦,不可移植性~~)

一个接着一个,看似平时非常习惯的东西,却一个一个的有着潜在的威胁:

class Parent
{
public:
virtual void Func() {...}
...;
};
class Child : public Parent
{
public:
virtual void Func()
{
static_cast<Parent>(*this).Func();
...; //子类自己的操作。
}
};

在子类中调用父类定义的函数。这是再寻常只是的事了。

但是以下的代码却非常危急:

上面这段简单的代码,子类的Func函数首先调用父类的,再做子类的操作。但是,这里的static_cast得到的是一个暂时副本,那么也就是说你的Func函数假设试图改动子类的成员,那么父类的部分是再暂时副本上做的,也就是说,你可能会得到一个“父类没有改动,子类改动了的”病态的对象。太可怕了,不是要尽量使用static_cast。要实现上述功能,直接指定作用域就可以,即使用Parent::Fun()函数来调用。

PS:尽量少用转型。

对于dynamic_cast,那就更应当敬而远之了,除了运行速度非常慢,尤事实上在多重继承或是多层继承中,简单的“类名搜索”成本就非常高了。

那么我们就必须知道,什么时候我们必须使用dynamic_cast呢?

如今你仅仅有“指向base”的指针或者引用,可是你须要的是对一个derived对象运行derivedclass的操作函数,你仅仅能靠它们来处理对象。这里全然能够避免使用dynamic_cast,方法为:

1不要忘了虚函数。。详细定义參见:

2不要忘了智能指针,使用容器存放指向derived类的智能指针,这样变消除了“使用base接口来处理对象”的必要性,关于智能指针,參见智能指针

请记得:

在注重效率的应用中,对转型动作“敬而远之”吧!

假设必须转型,那么记得封装在函数里面,不要让这些“恼人”的代码干扰用户代码。

使用新式转型,各司其职,不易出错,比較easy在源码中识别出来。

假设你认为你必须使用转型,请再想想,迈出这危急的一步的代价~~~

C++ 转型动作 尽量避免 以及 那些意想不到的威胁的更多相关文章

  1. Effective C++ -----条款27:尽量少做转型动作

    如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts.如果有个设计需要转型动作,试着发展无需转型的替代设计. 如果转型是必要的,试着将它隐藏于某个函数背后.客户随后可以调用该 ...

  2. [Effective C++ --027]尽量少做转型动作

    引言                                                                                                   ...

  3. 读书笔记_Effective_C++_条款二十七:尽量少做转型动作

    有关转型的几种做法,已经在早些的博客中写过了.这里先简单回顾一下,再讲一讲effective中对之更深入的阐述. 转型可以按风格可以分成C风格转型和C++风格转型两大类,C风格转型很容易看到,因为我们 ...

  4. 条款27:尽量少做转型动作(Minimize casting)

    NOTE : 1.如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts. 如果有个设计需要转型动作,试着发展无需转型的替代设计. 2.如果转型是必须要的,试着将它隐藏于某个函 ...

  5. [EffectiveC++]item27:尽量少做转型动作

  6. 代码优化—From <effective C++>

    1.尽可能的延后变量定义式的出现时间 不止应该延后变量的定义,直到非得使用该变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初值实参为止. 如果这样不仅能够避免构造和析构非必要对象,还可以避免无 ...

  7. Effective C++笔记(一)——条款26-29

    条款26:尽可能延后变量定义式的出现时间 为何要尽量延后? 当程序中途跳出而导致变量未被使用,但是必须进行构造和析构. 最佳初始化变量 直接在构造时指定初值比构造之后再赋值效率高(条款4) ... s ...

  8. Effective C++ 条款27

    尽量少做转型动作 尽量少做转型动作有什么目的?非常明显无非就是提高程序的稳定性.提高程序的运行效率. 那么.有哪些转型方式?每种方式都有什么弱点? 这是我们本节学习的重点. C++有四种转型: con ...

  9. Effective C++:规定27:尽量少做动作的过渡

    (一个)C风格遗留转换: (T)expression T(expression) (二)C++提供四种新式转型: (1)const_cast<T>(expression):去除表达式的常量 ...

随机推荐

  1. RabbitMQ系列之高可用集群

    为了实现高可用,我采用LVS+双节点RabbitMq , 架构图如下: 在RabbitMQ之前放了LVS, LVS 采用 rr 轮询算法 , 目的是将请求平均分配到两个真实节点,并配置5672端口监控 ...

  2. Spark(十六)DataSet

    Spark最吸引开发者的就是简单易用.跨语言(Scala, Java, Python, and R)的API. 本文主要讲解Apache Spark 2.0中RDD,DataFrame和Dataset ...

  3. caffe 如何训练自己的数据图片

    申明:此教程加工于caffe 如何训练自己的数据图片 一.准备数据 有条件的同学,可以去imagenet的官网http://www.image-net.org/download-images,下载im ...

  4. 决策树 (decision tree)

    内容学习于 ApacheCN github 定义: 分类决策树模型是一种描述对实例进行分类的树形结构.决策树由结点(node)和有向边(directed edge)组成.结点有两种类型:内部结点(in ...

  5. [java] java中的初始化顺序

    先看程序: package init_cls; class A{ {System.out.println("i am in the class A!");} static { Sy ...

  6. MySql 模糊查询、范围查询

    实例: SQL模糊查询,使用like比较关键字,加上SQL里的通配符,请参考以下: 1.LIKE'Mc%' 将搜索以字母 Mc 开头的所有字符串(如 McBadden). 2.LIKE'%inger' ...

  7. 20162307 课堂测试 hash

    20162307 课堂测试 hash 作业要求 利用除留余数法为下列关键字集合的存储设计hash函数,并画出分别用开放寻址法和拉链法解决冲突得到的空间存储状态(散列因子取0.75) 关键字集合:85, ...

  8. 洛谷P2657 Loj10165 SCOI2009 windy数

    题目描述 windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? 输入输出格式 输 ...

  9. iOS录音后播放声音小,AudioSessionInitialize failed,AudioQueueStart failed (-50)

    方法1: UInt32 audioRoute = kAudioSessionOverrideAudioRoute_Speaker; AudioSessionSetProperty(kAudioSess ...

  10. CentOS6.X关闭防火墙

    一.关闭防火墙 1.重启后永久性生效: 开启:chkconfig iptables on 关闭:chkconfig iptables off 2.即时生效,重启后失效: 开启:service ipta ...