More Effective C++
条款5:小心用户自定义的转换函数
1. 有两种函数可以让编译器实施隐式转换:
l 单个参数的构造函数:指只传递给它一个参数就可以调用的构造函数。
l 隐式的类型转换运算符
class Rational
{
public:
//convers int to Rational
Rational(int numerator = 0, int denominator = 1);
operator double()const; //converts Rational to double
};
2. 通常情况下不希望给任何类型提供类型转换函数。
3. explict关键字是为了解决隐式类型转换的问题而特别引入的。
条款8:理解new和delete在不同情形下的含义
1. new 操作符(new operator): Cat *pCat = new Cat(); 此处使用了new operator。它所完成的功能分成两部分。
l 分配足够的内存以便容纳所请求类型的对象。
l 调用构造函数初始化刚刚所分配的内存中的对象。
2. newoperator操作符调用一个函数来完成必须的内存分配,你可以重写或重载这个函数来改变它的行为。new operator操作符为分配内存所调用函数的名字是operator new。
Operator new通常申明为:void* operator new(size_t size)
3. placementnew函数
Widget *constructWidgetInBuffer(void *buffer, int widgetSize)
{
return new (buffer) Widget(widgetSize);
}
条款19:了解临时对象的来源
1. C++中真正的临时对象是不可见的——它们不出现在源代码中。如果一个对象被创建,而又不是在堆上被创建的,并且还没有名字,那这个对象就是临时对象。
2. 这种没有名字的对象通常出现在一下两种情况:
l 为了使函数调用能够成功而进行隐式类型转换
l 函数返回对象时所进行的隐式类型转换
3. 仅当以传值方式传递对象或把对象传递给声明为常量引用(reference-to-const)的参数时,才会发生这些类型转换。当传递一个非常量引用参数参数对象,就不会发生。
4. C++语言禁止为非常量引用产生临时对象。
条款25 一个用于对象计数的基类
1. 设计一个模版基类Counted:
#ifndef COUNTED_H_H_
#define COUNTED_H_H_
template <class BeingCounted>
class Counted
{
private:
static size_tnumObjects;
static const size_t maxObjects;
void init();//避À¨¹免a代䨲码?重?复¡ä
public:
classTooManyObjects
{
//for throwingexceptions
};
static size_tobjectCount()
{
returnnumObjects;
}
protected:
Counted();
Counted(constCounted& rhs);
~Counted()
{
--numObjects;
}
};
template<class BegingCounted>
size_tCounted<BegingCounted>::numObjects = 0;
template <class BeingCounted>
Counted<BeingCounted>::Counted()
{
init();
}
template <class BeingCounted>
Counted<BeingCounted>::Counted(const Counted& rhs)
{
init();
}
template <class BeingCounted>
voidCounted<BeingCounted>::init()
{
if(numObjects>= maxObjects)
throwTooManyObjects();
++numObjects;
}
#endif
2. 一个从该类继承的类Printer:
#ifndef PRINTER_H_H_
#define PRINTER_H_H_
#include "Counted.h"
class Printer : private Counted<Printer>
{
public:
static Printer*makePrinter();
static Printer*makePrinter(const Printer& rhs);
~Printer();
usingCounted<Printer>::objectCount;//make thisfunction public for clients of Printer
usingCounted<Printer>::TooManyObjects;
private:
Printer();
Printer(constPrinter& rhs);
};
Printer::Printer()
{
//proceed with normalobject construction;
}
Printer::Printer(const Printer& rhs)
{
}
Printer*Printer::makePrinter()
{
return new Printer();
}
Printer*Printer::makePrinter(const Printer& rhs)
{
return new Printer(rhs);
}
Printer::~Printer()
{
}
const size_tCounted<Printer>::maxObjects = 10;// 给基类的staticconst数据初始化#endif
3. 测试类:
#include "Printer.h"
#include <iostream>
using namespace std;
int main()
{
int count = 8;
Printer* p[8];
for (int i = 0; i < 8; ++i)
{
p[i] = Printer::makePrinter();
}
cout << Printer::objectCount() <<endl;
for (int i = 0; i < 8; ++i)
{
delete p[i];
}
return 0;
}
4. Counted完成了计数。并且继承是private的。在Printer中初始化的maxObjects.
本文探讨了C++编程中的几个关键技巧,包括如何谨慎地使用用户自定义转换函数以避免不必要的隐式转换,理解new和delete操作符的不同用法及其含义,以及识别临时对象的生成条件。同时,还介绍了一个用于对象计数的基类模板实现。
1097

被折叠的 条评论
为什么被折叠?



