(Effective C++)第五章 实现(Implementation)

7.1 条款26:尽可能延后变量定义式的出现时间(Postpone variable definitions as long as possible)
只要你定义一个变量而其类型带有一个构造函数或析构函数,那么当程序的控制流到达这个变量定义式时,你得承受构造成本;当这个变量离开作用域时,你得承受析构成本。
//这个函数过早定义变量”encrypted”
std:: string encryptPassword(const std::string & password)
{
use namespace std;
string encrypted;
if (password.length() < PASSWD_MIN_LEN)
{
    Throw logic_error("Password is too short");
}
 …
return encrypted;
}
示例7-1-1  加密函数过早定义变量
如果有个异常抛出出去,他就真的没有被使用,但是仍然付出了encrypted的构造和析构成本。更受欢迎的做法是:
std:: string encryptPassword(const std::string & password)
{
。。。 //检查长度
string encrypted(password); //过个copy构造函数定义并初始化
encrypt(encrypted)
return encrypted;
}
示例7-1-2  加密函数的改进
这段代码有两处改进:一是通过制作在构造时指定初值,比先构造对象再赋值效率高;二是延后定义,省去了检查长度抛异常的构造和析构成本。
但是循环咋办?
// 方法A:定义于循环体外
Widget w;
for (int i = 0; i < n; i++)
{
w = 取决于i的取值; //

}    // 方法B:定义于循环体内

for (int i = 0; i < n; i++)
{
Widget w(取决于i的取值); //

}
示例7-1-3  循环体与变量定义
做法A:1个构造函数+1个析构函数+n个赋值操作
做法B:n构造函数+n个析构函数
尤其是当n值很大士,做法A大体上比较高效。

7.2 条款27:尽量少做转型动作 (Minimize casting)
C++规则的设计目标之一是,保证“类型错误”绝不可能发生。不幸的是,转型(casting)破坏了类型系统(type system)。
C风格的转型动作:
(T)expression           //将expression转型为T
函数风格的转型动作:
T(expression)          //将expression转型为T
两种形式并无差别,我们称此为“旧式转型”(old-sytle casts)。
C++还提供四种新式转型:
const_cast(T)( expression )
dynamic_cast(T)( expression )
reinterpret _cast(T)( expression )
static_cast(T)( expression )
各自不同的目的:
?    const_cast通常被用来将对象的常量性转换(cast away the constness)。是唯一有此能力的C++ Sytle转型操作符。
?    dynamic主要是直线“安全向下转型”(safe downcasting),也就是用来决定某对象是否归属继承体系中的某个类型。耗费最大的转型动作。
?    reinterpret意图直线低级转型,实际动作可鞥呢取决于编译器,这也就表示不可移植。
?    static_cast用来强迫隐式转换(implicit conversion),例如,将non-const转为cosnt对象,或将int转换为double等等。它可以执行上述多种转换的反向转换,例如,将void*指针转为typed指针,将pointer-to-base转为pointer-to-derived。但是无法将const转为non-const——这个只有const-cast才办得到。

旧式转换仍然合法,但是新式转换更受欢迎。
使用旧式转换的时机是,当我调用一个explicit构造函数将一个对象传递给一个函数时。例如:
class Widget
{
 public:
    explicit Widget(int size);
};
void doSomeWork(const Widget &w);
doSomeWork(Widget(15));  //以一个int加上函数风格的转型动作创建一个Widget
doSomeWork(static_cast<Widget>(15));  ///以一个int加上C++风格的转型动作创建一个Widget
示例7-2-1  explicit构造函数转
任何一个类型转换往往真的令编译器编译出运行期间运算的码。
class Base{…};
class Derived : public Base {…};
Derived d;
Base *pb = &d;      //隐式将Derived*转换为Base* //隐患
这个例子表明,单一对象(例如一个类型为Derived的对象)可能拥有一个以上的地址(例如,“以Base*指向它”时的地址和“以Derived*指向它”时的地址)。即使在单一继承中也可能发生。对象的布局方式和它们的地址计算方式随编译器不同而不同,那意味着,在某一平台行得通,而在其他平台可鞥行不通。
class Window
{
 public:
    virtual void onReszie() {…}
};
class SpecialWindow:public Window
{
 public:
    virtual
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值