【转】effective C++读书笔记(二)

转自:http://hi.baidu.com/a024014/blog/item/617b690ac43e8b1a95ca6ba2.html

 

类和函数:设计与声明

条款18 :争取使类的接口完整并且最小

条款19 :分清成员函数,非成员函数和友元函数

如果 f 必须是虚函数,就让它成为 C 的成员函数。

operator>> 和 operator<< 决不能是成员函数。如果 f 是 operator>> 或 operator<< ,让 f 成为非成员函数。如果 f 还需要访问 C 的非公有成员,让 f 成为 C 的友元函数。

只有非成员函数对最左边的参数进行类型转换。如果 f 需要对最左边的参数进行类型转换,让 f 成为非成员函数。如果 f 还需要访问 C 的非公有成员,让 f 成为 C 的友元函数。

Eg:

Ostream& operator<<(ostream& output,const String& str){

    Output<<String.data;//String 是自己定义的一个类

}

条款20 :避免public 接口出现数据成员

    这个条款其实就是让我们用get 方法获取成员而避免把数据成员直接声明为public 。

条款21 :尽可能使用const

    Const char *p; 1

    Char const *p; 2

    Char *const p; 3

    Const char *const p; 4

    其中1=2 ,表示指针p 指向的内容是不可修改的常量;

    而3 表示p 指向的地址是不可修改的;

    4 则综合了前两者。基本上就是个就近原则,以* 为分界线,const 靠近谁,谁就是不可修改的。

    顺便提下,可以这样声明:

    Const int &p=3;//int &p=3; 是错的

Const Char *&const p=”hello”;//const char *&p=”hello” 是错的

另外,C++ 允许仅在const 方面有不同的成员函数重载,eg:

class String {

public:

...

// 用于非 const 对象的 operator[]

char& operator[](int position)

{ return data[position]; }

// 用于 const 对象的 operator[]

const char& operator[](int position) const

{ return data[position]; }

private:

char *data;

};

String s1 = "Hello";

cout << s1[0]; // 调用非 const

// String::operator[]

const String s2 = "World";

cout << s2[0]; // 调用 const

// String::operator[]

当方法为const 时,还要修改数据成员时,可以把数据成员修饰为mutable.

有时候,迫不得已,可以用const_cast 把const 性转掉。

条款22 :尽量用“传引用”而不用“传值”

    传递引用除了比传值高效之外,主要原因在于它避免了切割问题的出现,也就是不存在子类用父类变量传递时发生的切割,被去除了子类特有的部分,用引用实现动态绑定。

    当然在传递的变量类型很小,或者基类型时,用传值反而更快,因为引用的内部实现其实用的是指针,当char ,short,int ,直接传递值速度反而更快一些。

条款23 :必须返回一个对象时不要试图返回一个引用

    该条款主要就是为了保证程序的正确性,防止返回一个局部对象的引用。

条款24 :在函数重载和设定参数缺省值间慎重选择

`

条款25 :避免对指针和数字类型重载

    Eg:void f(int x);

       Void f(string *ps);

       F(0); // 调用f(int) 还是f(string *) ?

    上述结果是调用f(int) ,但是有时候我们并不希望编译程序这样理解。

    定义一个类NULL 如下可以解决问题:

const // 这是一个 const 对象 ...

class {

public:

template<class T> // 可以转换任何类型

operator T*() const // null 非成员指针

{ return 0; } //

template<class C, class T> // 可以转换任何类型

operator T C::*() const // null 成员指针

{ return 0; }

private:

void operator&() const; // 不能取其地址

// ( 见条款 27)

} NULL; // 名字为 NULL

此时调用f 函数时用f(NULL) 和f(0) 即可区分开来。

    当然, 作为重载函数的设计者,归根结底最基本的一条是,只要有可能,就要避免对一个数字和一个指针类型重载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值