- 博客(35)
- 收藏
- 关注
原创 effective C++笔记之条款40: 通过分层来体现“有一个”或“用…来实现”
分层:使某个类的对象成为另一个类的数据成员,从而实现将一个类构筑在另一个类之上,这一过程称为“分层”。公有继承的含义是“是一个”。对应地,分层的含义是“有一个”或“用…来实现”。Person对象“有一个”名字,地址,电话号码和传真号码。Set模板要求用来表示任意对象的集合,并且集合中没有重复元素。因为list可以包含重复对象,所以,用公有继承不行,因为Set“是一个”list是错误的,他不能包含重
2012-03-28 10:56:24 2993
原创 effective C++笔记之条款39: 避免“向下转换”继承层次
先看如下例子:class Person {…};class BankAccount{public: BankAccount(const Person *primaryOwner, const Person *jointOwner); virtual ~BankAccount(); virtual void makeDeposit(
2012-03-27 16:15:00 2912
原创 effective C++笔记之条款38: 绝不要重新定义继承而来的缺省参数值
先看如下类层次结构enum ShapeColor {RED, GREEN, BLUE};class Shape{public: virtual void draw(ShapeColor color = RED) const = 0; …};class Rectangle : public Shape{public: v
2012-03-26 11:34:44 2673
原创 effective C++笔记之条款36、37: 区分接口继承和实现继承、绝不要重新定义继承而来的非虚函数
条款36: 区分接口继承和实现继承作为类的设计者,有时希望派生类只继承成员函数的接口(声明)(也即是纯虚函数);有时希望派生类同时继承函数的接口和实现,但允许派生类改写实现(即虚函数);有时希望同时继承接口和实现,并且不允许派生类改写任何东西(非虚函数)。看如下这个类层次结构:class Shape{public: virtual void draw() c
2012-03-25 14:51:57 1666
原创 effective C++笔记之条款35: 使公有继承体现“是一个”的含义
D (Derived)公有继承于B(Base),实际上是:类型D的每一个对象也是类型B的一个对象,但反之不成立;B是一个比D更广泛的概念,D表示一个比B更特定概念;是在声明:任何可以使用类型B的对象的地方,类型D的对象也可以使用,因为每个类型D的对象是一个类型B的对象。相反。如果需要一个类型D的对象,类型B的对象就不行:每个D是一个B,但反之不成立。 1. 如下典型例子:class P
2012-03-25 11:38:12 920
原创 effective C++笔记之条款34: 将文件间的编译依赖性降至最低
1. 先看如下函数:class Person{public: Person(const sting& name, const Date& birthday,const Address& addr, const Country& country); virtual ~Person(); string name() const;
2012-03-24 15:08:25 1150
原创 effective C++笔记之条款33: 明智地使用内联
l 内联函数的基本思想在于将每个函数调用以它的代码体来代替。这种做法很可能会增加整个目标代码的体积。在一台内存有限的计算机里,过份地使用内联所产生的程序会因为有太大的体积而导致可用空间不够。过多的使用内联还会降低指令高速缓存的命中率,从而使取指令的速度降低,因为从主存取指令当然比从缓存要慢。l 另一方面,如果内联函数非常短,编译器为这个函数体生成的代码就会真的比为函
2012-03-21 19:29:21 979
原创 effective C++笔记之条款31、32: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针所指对象的引用、尽可能地推迟变量的定义
条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针所指对象的引用。l 返回一个局部对象的引用。局部对象在被定义时创建,在离开函数体时被销毁。当函数返回时,程序的控制离开了这个空间,所以函数内部所有的局部对象被自动销毁。因此,如果返回局部对象的引用,那个局部对象其实已经在函数调用者使用它之前被销毁了。l 返回函数内部用new初始化的指针
2012-03-20 20:02:01 1874
原创 effective C++笔记之条款30: 避免这样的成员函数:其返回值是指向成员的非const指针或引用,但成员的访问级比这个函数要低。
有如下三种情况:1.class Address { …};class Person{public: Address& personAddress() { return address; }private: Address address;}; Person scott(..);Address& addr = scott.personA
2012-03-19 20:47:52 1177
原创 effective C++笔记之条款29: 避免返回内部数据的句柄
const A a;是否会变化?答案取决于其成员函数的组成结构。先看一个String类:class String{public: String(const char *value); ~String(); operator char *() const; //转换String到char *private: c
2012-03-19 15:47:22 888
原创 effective C++笔记之条款28: 划分全局名字空间
l 全局空间最大的问题在于它本身仅有一个。在大的软件项目中,经常会有不少人把他们的定义放在这个单一的名字空间中,从而不可避免地导致名字冲突。l 解决方法:可以在全局符号前加上一些不大可能造成冲突的前缀。 另一个比较好的方法就是使用 C++ namespace 。namespace本质上和使用前缀的方法一样,只不过避免了别人总是看到前缀而已。用户可以通过三种方
2012-03-19 09:00:42 763
原创 effective C++笔记之条款27:如果不想使用隐式生成的函数就要显示地禁止它
l 习惯应该坚持下去,不管今天是什么日子。来自3月17日晚上9点半的总结。l 比如类模板Array,它所生成的类除了可以进行上下限检查外,其他行为和C++标准数组一样,但标准的数组是不允许数组间赋值的。设计中面临的一个难题是怎样禁止掉Array对象间的赋值操作。l 有如下两步禁止隐式生成的函数生成:声明这个函数(如operator=),并使
2012-03-17 21:43:44 901
原创 effective C++笔记之条款26:当心潜在的二义性
三种可能的情况1.类中构造函数与重载转换运算符间的二义性,如下所示:class B;class A{public: A(const B& b) { cout << "A()" << endl; }private: int data;};class B{public: B():data(0) {} operator A() const;private: i
2012-03-16 16:13:14 1061 2
原创 effective C++笔记之条款24、25:在函数重载和设定参数缺省值间慎重选择、避免指针和数字类型重载
条款24:在函数重载和设定参数缺省值间慎重选择l 会对函数重载和设定参数缺省值产生混淆的原因在于,他们都允许一个函数以多种方式被调用。l 到底用哪个取决于两个问题。确实有那么一个值可以作为缺省吗?要用到多少种算法?一般来说,如果可以选择一个合适的缺省值并且只是用到一种算法,就使用缺省值,否则,就用函数重载。l 设定参数缺省值
2012-03-15 15:09:29 942
原创 effective C++笔记之条款23:必须返回一个对象时不要试图返回一个引用
l 想要返回一个对象的引用时,重载乘号操作符容易犯以下几个错误,:1 返回一个局部对象的引用2 在堆上创建一个对象,然后返回它的引用,无法去delete它,造成内存泄漏3 返回静态对象的引用,导致两个不同对象的==操作符总是为真。l 所以正确的乘法操作符应该返回一个新对象。这会导致operator的返回值构造和析
2012-03-14 21:34:33 1476
原创 effective C++笔记之条款22:尽量使用“传引用”而不用“传值”
l 通过值来传递一个对象的具体含义是由这个对象的类的拷贝构造函数定义的。这使得传值成为一种非常昂贵的操作。为避免这种潜在的昂贵的开销,就不要通过值来传递对象,而要通过引用。这会非常高效,因为没有新的对象被创建。而且避免了“切割问题”。如下所示:class Window{public: sting name() const; virt
2012-03-14 21:25:45 961
原创 effective C++笔记之条款20、21:避免public接口出现数据成员、尽可能使用const
条款20: 避免public接口出现数据成员 l 如果接口里存在数据成员,用户每次访问类的成员时候会想是该用括号还是不该用括号。如果每个成员都是函数,就不用多想了。l 采用函数可以更精确地控制数据成员的访问权。如果使数据成员为public,每个人都可以对它读写;如果用函数来获取或设定它的值,就可以实现禁止访问、只读访问和读写访问、只写访问。l
2012-03-13 17:13:16 939
原创 effective C++笔记之条款19:分清成员函数,非成员函数和友元函数
这是很重要的一个条款。l 成员函数和非成员函数最大的区别在于成员函数可以是虚拟的而非成员函数不行。所以,如果有个函数必须进行动态绑定,而虚拟函数必定是某个类的成员函数。但如果函数不必是虚拟的,情况就稍微复杂一点。l 只要能避免使用友元函数就要避免,因为,和现实生活中差不多,友元(朋友)带来的麻烦往往比它(他/她)对你的帮助多。 l 结论如下
2012-03-12 14:57:11 1198
原创 effective C++笔记之条款18:争取使类的接口完整并且最小
l 类的用户接口是指使用这个类的程序员所能访问得到的接口。典型的接口里只有函数存在,因为在用户接口里放上数据成员会有很多缺点。l 一个完整的接口是指那些允许用户做他们想做的任何合理的事情的接口。l 一个最小的接口,是指那种函数尽可能少、每两个函数都没有重叠功能的接口l 大的类接口缺点:1 接口函数越多,以后的潜在
2012-03-12 14:55:14 568
原创 effective C++笔记之条款17: 在operator=中检查给自己赋值的情况
l 注意别名:同一个对象有两个以上的名字。别名可以以大量任意形式的伪装出现,所以在写函数时一定要考虑到它。l 在赋值运算符要特别注意可能出现的别名的情况,有两个理由:1. 效率。如果可以在赋值运算符函数体的首部检测到是给自己赋值,就可以立即返回,从而可以节省大量的工作,否则必须去实现整个赋值操作。2. 更重要的原因。一个赋值运算符
2012-03-11 14:38:38 902
原创 effective C++笔记之条款16: 在operator=中对所有数据成员赋值
1. 写赋值运算符时,必须对对象的每一个数据成员赋值。每增加一个数据成员,同时要更新构造函数和赋值运算符。2. 对于指针成员,赋的值是指针所指的值,而不是指针本身。3. 涉及继承时,应注意Base成员的赋值操作。如下情况:class Base{public: Base(int temp = 0):x(temp) {}pr
2012-03-11 14:23:47 712
原创 effective C++笔记之条款15:让operator=返回*this的引用
l 缺省版本的operator=函数具有如下形式:C&C::operator=(const C&);l 返回值常犯的错误:返回void,妨碍了连续赋值操作;返回const对象的引用,使该语句不能通过(w1 = w2)= w3。l 即使重载了赋值操作符,返回的也是类的对象的引用。如标准string类型提供了两个不同版本的赋值运算符,如下所示:
2012-03-11 14:02:21 793
原创 effective C++笔记之条款14:确定基类有虚析构函数
l 当通过基类的指针去删除派生类的对象,而基类有没有虚析构函数时,结果将是不可确定的。派生类的析构函数永远不会被调用。所以,应将基类的析构函数为virtual:对象内存释放时,基类和派生类的析构函数都会被调用。l 如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚是一个坏主意。因为将会带来隐藏的vptr成员,使
2012-03-10 13:37:46 1232
原创 迷上了这里,迷上了写CSDN博客
记得前年注册的账号吧,那时候刚上研一,还是个很菜的菜鸟,注册CSDN也就是发点很基础的问题,下载点资源,但在实验室的大牛影响下,我也开始迷上了写博客,我觉得写博客在给别人带来方便、经验的同时,也能促进人进步。我每发表一次博客,我都会将做的笔记重新审读一遍,因为我觉得发在网上,你就应该对自己发表的文章负责,错别字什么的尽量要少,这不仅加深了我的理解,更将整个资料做得更完整。下半年就要找工作了。。。时
2012-03-09 23:50:40 1015 3
原创 启动界面的实现(SDK)
这个是主窗口的消息处理函数LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){case WM_CREATE: //处理WM_CREATE消息,弹出对话框, 这里我就用了系统自己添加的关于窗口,你可以自己再添加个窗口 DialogBox(hInst, MAKEINTRES
2012-03-09 18:14:45 896
原创 effective C++笔记之条款13: 初始化列表中成员列出的顺序和它们在类中声明的顺序相同
l 类成员是按照它们在类里被声明的顺序进行初始化的,和他们在成员初始化列表中列出的顺序没有关系。l 如果成员按照它们在初始化列表上出现的顺序被初始化,那么w1和w2中的数据成员被创建的顺序就会不同。对一个对象的所有数据成员来说,他们的析构函数被调用的顺序总是和它们在构造函数里被创建的顺序相反。那么,如果允许上面的情况(即,成员按它们在初始化列表上出现的顺序被初始化)
2012-03-09 16:00:29 679
原创 effective C++笔记之条款12: 尽量使用初始化而不要在构造函数里赋值
l const和引用数据成员只能用初始化,不能被赋值。l 对数据成员同时声明const和引用,这样就生成了一个其名字成员在类外可以被修改而在内部是只读的对象。l 对象的创建分为两步:1.数据成员初始化2.执行被调用构造函数体内的动作。l 对有基类的对象来说,基类的成员初始化和构造函数体的执行发生在派生类的成员初始化和构造函数体的执
2012-03-09 15:58:34 771
原创 effective C++笔记之条款11: 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
l 当类里有指针,并且需要动态分配时,如果没有定义自己的拷贝构造函数和赋值操作符,使用编译器合成的缺省的操作,将会带来一些严重的后果,如内存泄漏(调用赋值操作符时)、调用两次delete(如以类对象进行传值调用、调用拷贝构造函数时)。l 用delete去删除一个已经被删除的指针,其结果是不可预测的。l 只要类里有指针,就要写自己版本的拷贝构造函数和
2012-03-09 12:55:51 1050 1
原创 effective C++笔记之条款9、10:避免隐藏标准形式的new、如果写了operator new 就要同时写operator delete
条款9: 避免隐藏标准形式的newl 当在类里增加了一个带多个参数的operator new函数。可能会调用不到全局(标准)的new,这时就会出错。l 两个办法:在类里写一个支持标准形式的operator new,它和标准new做同样的事。可用一个高效的内联函数来封装实现;为每一个增加到operator new的参数提供缺省值。l 无论用哪种方
2012-03-08 14:37:33 820
原创 effective C++笔记之条款8: 写operator new和 operator delete 时要遵循常规
l 自己重写operator new时,很重要的一点是函数提供的行为要和系统缺省的operator new一致。实际做起来就是:要有正确的返回值;可用内存不够时要调用出错处理函数;处理0字节内存请求的情况。此外,还要避免不小心隐藏了标准形式的new。(条款9)l operator new包含一个无限的循环,跳出循环的唯一办法是内存分配成功或出错处理函数完成了条款7所
2012-03-08 14:23:24 759
原创 effective C++笔记之条款7:预先准备好内存不够的情况
l operator new在无法完成内存分配请求时会抛出异常。万一new真的产生异常该怎样处理?l 当内存分配请求不能满足时,调用你预先指定的一个出错处理函数。这个方法基于一个常规,即当operator new不能满足请求时,会在抛出异常之前调用客户指定的一个出错处理函数--一般称之为new-handler函数。l 制定出错处理函数用set_ne
2012-03-08 14:19:00 1001
原创 类中的static 数据成员和c++ primer中提到的static的深入思考
类的静态数据成员可以在class的定义中直接初始化,但要清楚:这只是声明并给它提供了一个初值而已,还必须在某一个编译单元中把它定义一次(即分配内存)。如在 C++ primer中出现的这种情况:class Account { public: // interface functions here void applyint()
2012-03-07 19:34:11 1434
原创 关于复制构造函数(拷贝构造函数)和赋值操作符(拷贝赋值函数)应该知道的
每个类只有一个析构函数,但可以有多个构造函数(包含一个拷贝构造函数,其他的为普通构造函数)和多个赋值函数(包含一个拷贝构造函数,其他的为普通构造函数)。一般的,对于任何一个类A,如果程序员不显示地声明和定义上述函数,c++编译器将自动为A产生4个public inline的默认函数。 默认的拷贝构造函数和默认的赋值构造函数均采用“按成员拷贝”默认方式来实现。但是,基本类型变量(包括
2012-03-07 17:25:30 1303 2
原创 effective C++笔记之条款6:析构函数里对指针成员调用delete
l 在大多数情况下,执行动态分配的类都在构造函数里用new分配内存,然后在析构函数里用delete释放内存。 l 增加一个指针成员意味着以下工作:1 在每个构造函数里对指针进行初始化。对于一些构造函数,如果没有内存要分配给指针的话,指针要被初始化为0(NULL);2 删除现有的内存,通过赋值操作符分配给指针新的内存;3
2012-03-07 17:04:36 1444
原创 effective C++笔记之条款5:对应的new和delete要采用相同的形式
l 用new的时候会发生两件事。首先,内存被分配(通过operator new函数),然后,为被分配的内存调用一个或多个构造函数。用delete的时候,也有两件事发生:首先,为被释放的内存调用一个或多个析构函数,然后,释放内存(通过operator delete函数)。 l 对于delete来说有这样一个问题:内存中有多少个对象要被删除?答案决定了将有多少个析构
2012-03-07 16:55:54 834
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人