EffecticeC++-----1-2章(条款1-12)

条款01
视C++为一个语言联邦

条款02
尽量以const,enum,inline替换#define

宁可以编译器替换预处理器

1.
#define ASPECT_RATIO 1.653
//采用上述方法时,若在编译过程中发生错误,错误信息将提及1.653而不会提及ASPECT_RATIO

const double AspectRatio = 1.653
//采用该方法时,错误信息中就会提及AspectRatio

2.
//若要在头文件内定义一个常量的char*类型字符串:
const char* const authorName = "Scott Meyers"
//前一个const限制字符串,后一个const限制指针

3.
//#define不重视作用域
class CostEstimate
{
private:
	static const double FudgeFactor;
	...
};
const double CostEstimate::FudgeFactor = 1.35;

4.
//the enum hack补偿做法
class GamePlayer
{
private:
	enum{NumTurns = 5};
	
	int scores[NumTurns];
}

条款03
尽可能使用const

1.
char greeting[] = "Hello"
char * p = greeting;	//non-const pointer,non-const data
const char * p = greeting;	//non-const pointer,const data
char * const p = greeting;	//const pointer,non-const data
const char * const p = greeting	//const pointer,const data

2.
//const成员函数
class TextBlock
{
public:
	...
	const char& operator[](std::size_t position)const	//operator[] for const对象
	{
	return text[position];
	}
	char& operator[](size::size_t position)
	{
	return text[position];
	}
private:
	std::string test;
}
//例子
TextBlock tb("hello");
const TextBlock ctb("world");
//
ctb[0] = 'x'	//错误

3.
//const对象无法访问非const部分,解决方法mutable关键字
class CTextBlock
{
public:
	...
	mutable int textLength;
}
...
const CTextBlock sample;
sample.textLength = 10	//在加mutable下成功

4.
const char& operator[](param)const
{
	...
}
char& operator[](param)
{
	...
}
//上述造成大量代码重复
//下为解决方法
const char& operator[](param)
{
	...
}
char& operator[](param)
{
	return
		const_cast<char&>
			static_cast<const TextBlock&>(*this)[position];
}

条款04
确定对象被使用前已经初始化

1.
//一种初始化方法,效率更高
class ABEntry
{
public:
	int a,b;
	ABEntry(int x,int y):a(x),b(y)
	{}
}

2.
//确保初始化的一种方法
class FileSystem
{
public:
	...
	std::size_t numDisks() const;
}

FileSystem& tfs()
{
	static FileSystem fs;
	return fs;
}

class Diretory
{
public:
	Directory(param)
	{
		something = tfs().something;	
	}
	...
}

条款05
了解C++默默编写并调用哪些函数

1.
class Empty
{
	//编译器自动添加:
	Empty(){...}
	Empty(const Empty& rhs){...}
	~Empty(){...}
	Empty& operator=(const Empty& rhs){...}
}

2.
class NameObject
{
public:
	string& nameValue;
	const int objValue;
	
	NameObject(string& name,int obj){...}	//赋值给上述变量
}
...
NameObject a("i am a",1);
NameObject b("i am b",2);
a = b;	//拒绝编译引用和常量的赋值,因为不合法

条款06
若不想使用编译器自动生成的函数,明确拒绝

1.
//一下类无法使用=号赋值,也无默认赋值构造函数
class Home
{
private:
	Home(const Home&);
	Home& operator=(const Home);
	...
}
2.
class Uncopyable
{
protect:
	Uncopyable(){}
	~Uncopyable(){}
	Uncopyable(const Uncopyable&);
	Uncopyable& operator=(const Uncopyable&);
};

class Home:private Uncopyable{...};

条款07
为多态基类声明virtual析构函数

1.
class Time
{
public:
	Time();
	virtual ~Time();
}
...
class Atom : public Time
{
public:
	~Atom(){...}
}
...
Time * a = new Atom;
delete a;//以Time的类身份删除
//若此时Time析构函数Atom的析构函数

条款08
别让异常逃离析构函数

1.
//场上同时存在两个异常时,结果不可预测
class Widget
{
public:
	...
	~Widget(){...}	//假设可抛出异常
}
void doSomething()
{
	vector<Widget> v;
	...
}
//doSomething销毁时可能出现两个异常

2.
class DBConnection
{
public:
	...
	static DBConnection create();
	void close();
}

class DBConn
{
public:
	...
	~DBConn()
	{
		db.close();
	}
private:
	DBConnection db;
}
...
{
DBConn dbc(DBConnection::create());
...
}
...
DBConn::~DBConn()
{
	try{db.close();}
	catch{...}	//两种方法,吞下异常,记录异常
}

条款09
绝不在构造和析构过程中调用virtual函数

class Transaction
{
public:
	Transaction()
	{
		...
		log();
	}
	virtual void log()const = 0;
}
...
class Buy: public Transaction
{
public:
	virtual void log()const;
}
...
Buy b;
//当创建b时先调用Transaction的构造函数,但是Transaction的构造函数里的log是调用的Transaction的log
//此时的virtual不具有virtual性质

条款10
令operator=返回一个reference to * this

class Widget
{
public:
	...
}
...
Widget& operator=(const Widget& rhs)
{
	...
	return *this;
}

条款11
在operator=中处理自我赋值

class Widget {...}
Widget w;
...
w = w;

//
class Bitmap{...}
class Widget
{
	...
private:
	Bitmap* pb;
}
...
Widget&
Widget::operator=(const Widget& rhs)
{
	delete pb;
	pb = new Bitmap(*rhs.pb);
	return *this;
}
//以上例子若发生自我赋值(w=w),则delete时将把两个地方的pb都删除
//解决方法
{
	...
	if(this == &rhs) return *this;	//加一个判断条件
}
//以上方案并不绝对安全
//解决方法2
Widget& Widget::operator=(const Widget& rhs)
{
	Bitmap* pOrig = pb;
	pb = new Bitmap(*rhs,pb);
	delete pOrig;
	return *this;
}
//以上方法保证在删除前创建完新的对象
//解决方法3
class Widget
{
...
void swap(Widget& rhs);	//交换this与rhs的数据
...
};
...
Widget& Widget::operator=(const Widget& rhs)
{
	Widget temp(rhs);
	swap(temp);
	return *this;
}

条款12
复制对象时勿忘其每一个部分

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值