C++设计与声明超详细讲解_第1页
C++设计与声明超详细讲解_第2页
C++设计与声明超详细讲解_第3页
C++设计与声明超详细讲解_第4页
C++设计与声明超详细讲解_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第C++设计与声明超详细讲解目录让接口被正确使用不易被误用宁以pass-by-reference-to-const替换pass-by-value必须返回对象时将成员变量声明为private以non-membernon-friend替换member函数non-member考虑写出一个不抛出异常的swap函数

让接口被正确使用不易被误用

除非有好的理由,否则应该让你的types的行为与内置types一致,请拿ints做范本

提供行为一致的接口!

阻止误用的办法包括建立新类型,限制类型上的操作,束缚对象值(比如要统计年月日,限制月的大小在1-12),消除客户的资源管理责任(智能指针)

shared_ptr支持定制型删除器,可被用来自动解除互斥锁等

宁以pass-by-reference-to-const替换pass-by-value

值传递要调用copy构造函数,释放时要调用多次析构函数(有副本),费时

const的必要性:引用传递代替值传递时,确保不会对传入的数据做改变

防止被切割:

classWindow{

public:

virtualvoiddisplay();

classWindowWithScrollBars:publicWindow{

public:

virtualvoiddisplay();

voidshow(Windoww){

w.display();

}

当用一个WindowWithScrollBars对象传入show时,因为是值传递,会导致其特化信息被切割,变成了一个Window对象!无法多态了!

应该如下:传进来的窗口是什么类型,w就表现出哪种特性

voidshow(constWindoww){

}

说到底,引用是指针实现出来的,引用传递说到底也是传递的指针,如果有一个对象属于内置类型,值传递效率会比引用传递效率高一些。

值传递对于内置类型和STL的迭代器和函数对象来说代价不贵,其他类型还是选用const引用传递好!

必须返回对象时

别妄想返回reference

不是所有情况都是引用传递好

constAoperator*(constArhs){

Aresult(rhs);//调用构造函数

returnresult;

}

返回了一个result的引用,但result是一个局部变量,离开作用域就被析构了!!!

引用不能返回一个局部对象,否则一败涂地

一个必须返回新对象的函数的做法是:就让他返回一个新对象呗

constAoperator*(constArhs){

Aresult(rhs);//调用构造函数

returnA(rhs);

}

承受一个operator*构造和析构函数的代价即可

绝对不要返回一个指针或引用指向一个localstack对象(出作用域会被析构),或返回引用指向一个heap-allocated对象(无法保证合理的delete),或返回指针或引用指向一个localstatic对象而有可能同时需要多个这样的对象(一个指针修改了指向对象的参数后,其他指针指向的参数也被修改了)

将成员变量声明为private

语法一致性:成员变量不是public,用户只能通过public里的相应函数来访问成员变量,用户使用时就都有一致的使用规则(全都要使用小括号等)

使用函数可以对成员变量的处理有更精确的控制,如可以编写const函数实现只读访问,不加const实现读写访问等

封装性,防止成员变量被更改

假如有一个public成员变量,我们最终取消了它,所有使用它的代码都会被破坏,假如有一个protected成员变量,我们最终取消了它,所有使用它的派生类都会被破坏。因此protected其实并不比public更加具有封装性

说到底,选择private就好

以non-membernon-friend替换member函数

能够访问private成员变量的函数只有class的member函数加上friend函数,如果要在一个member函数(不只可以访问private数据,也能取用private函数、enums、typedefs等)和一个non-member,non-friend函数做抉择,较好封装性的时后者。因为它并不增加能够访问class内private成分的函数数量

将所有便利函数放在多个头文件内但同属于一个命名空间,用户可以轻松添加这一组便利函数,即可以添加更多的non-member,non-friend函数到此命名空间

参考C++标准程序库,vector、algorithm等,导入头文件再进行调用,即可完成很多事情

non-member

若所有参数皆需要类型转换,请为此采用non-member函数

classRational{

public:

Rational(intnumerator=0,intdenominator=1);

intnumerator()const;

intdenominator()const;

constRationaloperator*(constRationalrhs)const;

Rationalonehalf(1,2);

Rationalresult=onehalf*2;//很好!

Rationalresult=2*onehalf;//不行!

原因在于:

result=onehalf.operator*(2);//发生了隐式转换得益于之前没有将构造函数声明为explicit

result=2.operator*(onehalf);

2没有相应的class,没有operator*成员函数,当然无法执行

结论为:只有当参数被列于参数列内,这个参数才是隐式转换的合格参与者

改变做法为将operator*变成non-member函数,允许编译器在每个实参上执行隐式转换

operator*是否应该成为class的一个friend函数呢?否定的,因为operator*完全可以借用Rational的public接口完成任务,这告诉我们:member函数的反面是non-member,而不是friend

如果你需要为某个函数的所有参数(包括this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是non-member

考虑写出一个不抛出异常的swap函数

当做swap时,如果交换内部的指针,效率就高了呀

以指针指向一个对象,内含真正的数据,即pimpl手法(pointertoimplementation)

classWidgetImpl{

public:

private:

inta,b,c;

classWidget{

public:

voidswap(Widegetother){

usingstd::swap;//必要的,在找不到class里的swap函数调用此函数

swap(p,other.p);

private:

WidgetImpl*p;

//修订后的std::swap特化版本

namespacestd{

template

voidswapWidget(Widgeta,Widgetb)

a.swap(b);//调用a的swap成员函数

}

这种方法和STL有一致性,因为STL也提供有public的成员函数和std::swap的特化版本

如果swap的默认版本的效率你可以接受,那不需要做任何事

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论