class A{
public:
A(int aa): a(aa) {}
private:
int a;
};
class B{
public:
explicit B(int bb = 0): b(bb) {}
private:
int b;
};
void funa(A a)
{
cout << "right" << endl;
}
void funb(B b)
{
cout << "right" << endl;
}
int main(int argc, const char * argv[]) {
// insert code here...
B objB1;
funb(objB1);
funa(28);
return 0;
}
可以编译通过的,然后
funb(28)
无法通过编译,原因是B的定义中使用了explicit关键字,阻止了构造函数被用来执行隐式类型转换。funa会自动调用A的构造函数构造A类型的对象。下面两种方式都可以通过编译:
funb(B(28))
funb(static_cast<B>(15))
第一种方式是调用B的构造函数进行了显式转换,第二种方式使用了static_cast,也创建了B对象。(Effective C++ I条款27)
在条款27中提到的Tips:
(1)const_cast:执行常量型转移的动作,也只有该动作可以将const转为non-const;
(2)如果Base和Derive类都实现了virtual function(例如onResize),那么如果在Derive类中如果要调用Base中的onResize,调用方式是Base::onResize(); 而非static_cast<Base>(*this).onResize(),原因是这种方式会导致先创建*this指针的副本,转换为Base类,然后更改了副本的某些成员,但*this指针所指并没有改变。
在条款34中提到的Tips:
(1)A是base类,B、C分别public继承自A,A中定义了纯虚函数fly(),在B、C中必须实现fly;但在A中也可以有A的纯虚函数实现,实现后可以在B、C中以A::fly()的形态调用。
导读中的Tips:
class Widget{
public:
Widget(); //default构造函数
Widget(const Widget& rhs); //copy构造函数
Widget& operator=(const Widget& rhs); //copy assignment操作符
};
Widget w1; //调用default构造函数
Widget w2(w1); //调用copy构造函数
w1 = w2; //调用copy assignment
Widget w3 = w2; //调用copy构造函数
判断的关键是:是否有新的对象被定义。有的话就有构造函数被调用。
条款3中的Tips:
(1)将const实施于成员函数的目的,是为了确认该成员函数可作用于const对象身上。
(2)两个成员函数如果只是常量性不同,可以被重载。
(3)如果函数的返回类型是个内置类型,那么改动函数返回值从来就不合法。
条款4中的Tips:
(1)singleton模式
作用是保证一个类只有一个实例,并提供全局唯一的访问点。一个实例:
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
class Singleton
{
private:
static Singleton* pInstance;//静态成员,保存对象的唯一实例
Singleton();//私有化构造函数,使其无法在类外实例化
public:
static Singleton* Instance();
//void Destroy();
static void Destroy();
};
#endif
#include "Singleton.h"
#include <iostream>
using namespace std;
Singleton* Singleton::pInstance = NULL;
Singleton::Singleton()
{
cout<< "Singleton..." << endl;
}
Singleton* Singleton::Instance()
{
if(NULL == pInstance)
{
pInstance = new Singleton();
}
return pInstance;
}
void Singleton::Destroy()
{
delete pInstance;
pInstance = NULL;
cout<< "Destroy..." << endl;
}
条款5中的Tips:
(1)如果你声明了一个构造函数,编译器不再为该类创建默认无实参构造函数。
条款6中的Tips:
(1)实现一个对象不可被复制的类:如果你不显式定义copy构造函数和copy assignment函数,编译器会自动为你实现这两个函数,所以我们的做法是定义private的copy构造函数和copy assignment 函数。
条款7中的Tips:
(1)如果基类Base的析构函数没有被定义为virtual,在用基类指针销毁一个Derive对象时,会发生derived成分没被销毁的情况。解决方案是将基类的析构函数定义为virtual。
(2)任何带有virtual函数的类机会都需要一个virtual析构函数。
(3)如下代码:
#include <iostream>
using namespace std;
class Base{
public:
virtual ~Base() {cout<< "base!" << endl;}
};
class Derive:public Base{
public:
~Derive() { cout << "derive!" << endl;}
};
int main(int argc, const char * argv[]) {
// insert code here...
Base* d = new Derive();
delete d;
return 0;
}
输出为
derive!
base!
说明当Derive对象析构时调用顺序还是derive然后base,即使当Base的析构函数被定义为virtual。条款11中的Tips:
(1)防止自我赋值问题的有效做法是证同测试。