第四章:设计与声明(二)
必须返回对象时,别妄想返回其reference
class Rational
{
public:
Rational(int numerator=0,int deominator = 1);
...
private:
int n,d;
friend const Rational operator*(const Rational& lhs,const Rational& rhs);
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
函数创建新对象可以在stack空间或heap空间创建。
stack空间:
const Rational operator*(const Rational& lhs,const Rational& rhs)
{
Rational result(lhs.n*rhs.n, lhs.d*rhs.d);
return result;
}
1
2
3
4
5
2
3
4
5
注意**:任何函数如果返回一个reference指向某个local对象,而local对象回在函数退出前被销毁,因此返回值无效。**(返回一个指针指向某个local对象也是同理)
heap空间:
const Rational& operator*(const Rational& lhs,const Rational& rhs)
{
Rational* result = new Rational(lhs.n*rhs.n, lhs.d*rhs.d);
return *result;
}
1
2
3
4
5
2
3
4
5
注意:何时调用delete函数释放申请的heap空间?
正确写法:
inline const Rational operator*(const Rational& lhs,const Rational& rhs)
{
return Rational(lhs.n*rhs.n, lhs.d*rhs.d);
}
1
2
3
4
2
3
4
将成员变量声明为private
注意事项:
将成员变量声明为private。这可赋予客户访问数据的一致性、可细微划分访问控制、允许约束条件获得保证,并提供clss作者以充分的弹性。(将成员变量隐藏在函数接口的背后,可以为“所有可能的实现”提供弹性;只读访问、读写访问函数;class约束条件获得维护,因为只有成员函数可以影响它们;)
protected并不比public更具封装性。
其实只有两种访问权限:private(提高封装)和其他(不提供封装)。
宁以non-member、non-friend替换member函数
声明成员变量为private能保证只有class的member函数加上friend函数可以访问它们。因此,在一个member和一个non-member,non-friend函数都能提供相同函数功能的情况下,应该优先选用non-member,non-friend函数,因为它并不增加“能够访问class内之private成分”的函数数量,所以较好的维持了class的封装性。
例如,WebBrowser类中已经实现了清理缓存,历史记录以及cookies的操作,可以创建一个non-member,no-friend函数并且位于WebBrowser所在的同一个namespace内,即实现了用户可以扩展自定义的函数。
//WebBrowser.h
namespace WebBrowserStuff{
class WebBrowser
{
public:
WebBrowser();
~WebBrowser();
void clearCache();
void clearHistory();
void removeCookies();
private:
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//WebBrowserClear.h
namespace WebBrowserStuff{
class WebBrowser;
void clearBrowser(WebBrowser& wb)
{
wb.clearCache();
wb.clearHistory();
wb.removeCookies();
}
} //WebBrowserStuffs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14