Effective C++ 条款26、27

条款26 尽可能延后变量定义式的出现时间

尽可能延后变量定义式出现时间,在定义的同时完成copy构造函数。

string encryptPassword(const string& password) {
	using namespace std;
	if (password.length() < MinimumPasswordLength) {
		throw logic_error("Password is too short");
	}
	string encrypted(password);//延后变量定义式出现时间,在定义的同时完成copy构造函数。
	return encrypted;
}
我们不只应该延后变量的定义,直到非得使用该变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初值实参为止。

条款27 尽量少做转型动作

尽可能使用C++中的新式转型,尽管C中的强制类型转换也适用。

const_cast<T>(expression)
dynamic_cast<T>(expression)
reinterpret_cast<T>(expression)
static_cast<T>(expression)

i、const_cast被用来将对象的常量属性转除(这是唯一具有去常量特性的C++转型操作符);

ii、dynamic_cast主要用来执行“安全向下转型(即base class到derived class的转型)”,也就是用来决定某对象是否归属继承体系中的某个类型。唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。

iii、reinterpret_cast意图执行低级转型,实际动作(及结果)可能取决于编译器。例如将一个int*转型为一个int。

iv、static_cast用来强迫隐式转换,如将non-const对象转为const对象,或将int转为double;再如将void*指针转为typed指针,将pointer-to-base转为pointer-to-derived。

a、以下转型注意点1

class Window {
public:
	virtual void onResize(){...}
	...
};
class SpecialWindow :public Window {
public:
	virtual void onResize() {
		static_cast<Window>(*this).onResize();//derived onResize实现代码
		                                      //将*this转型为Window,然后调用其onResize,行不通,见分析
	}
};
上述程序将*this转型为Window,对函数onResize的调用也因此调用了Window::onResize。但恐怕的是,它调用的并不是当前对象上的函数,而是稍早转型动作所建立的一个*this对象的base class成分的暂时副本身上的onResize! 可怕,因为我还是没有理解它为什么会这样做,但正确调用base class内的成员函数方法如下,
class SpecialWindow :public Window {
public:
	virtual void onResize() {
		Window::onResize();//调用Window::onResize作用于*this身上,此处使用了作用域操作符
	}
};

b、以下转型注意点2

之所以需要dynamic_cast,通常是想在一个我们认定为derived class对象身上执行derived class操作函数,但手头上却只有一个“指向base”的pointer或reference,于是只能靠它来处理对象。当然,我们建议避免使用dynamic_case转型。解决办法如下,

方法一:使用容器并在其中存储直接指向derived class对象的指针(通常是智能指针),如此便消除了“通过base class接口处理对象”的需要。

class Window{...};
class SpecialWindow :public Window {
public:
	void blink();
};
typedef vector<shared_ptr<SpecialWindow>> VPSW;
VPSW winPtrs;
...
for (VPSW::iterator iter = vinPtrs.begin(); iter != winPtrs.end(); ++iter)
	(*iter)->blink;

该方法的弊端就是无法在同一个容器内存储指针“指向所有可能的各种Window派生类”。故引出法二。

方法二:通过base class接口处理“所有可能的各种Window派生类”,在base class内提供virtual函数做对各个Window派生类做的事。

class Window {
public:
	virtual void blink();
};

class SpecialWindow :public Window {
public:
	virtual void blink() { }
};

typedef vector<shared_ptr<Window>> VPSW;
VPSW winPtrs;
//此处就是多态的实际运用啦!perfect!!
for (VPSW::iterator iter = vinPtrs.begin(); iter != winPtrs.end(); ++iter)
	(*iter)->blink();

以上内容均来自Scott Meyers大师所著Effective C++ version3,如有错误地方,欢迎指正!相互学习,促进!!

猜你喜欢

转载自blog.csdn.net/TT_love9527/article/details/80563281