C++
文章平均质量分 80
刘清涛
这个作者很懒,什么都没留下…
展开
-
条款40:明智而审慎地使用多重继承
//MI(multiple inheritance), 程序有可能从一个以上的base classes继承相同名称(如函数、typedef等等),那会导致较多的歧义机会//为了解决歧义你可能需要指明调用的是哪个base class的函数//会导致要命的“钻石型多重继承”,//如: class B1 : public B; class B2 : public B; class C : p...转载 2018-07-16 08:44:44 · 163 阅读 · 0 评论 -
条款29:为“异常安全”而努力是值得的
/**********条款14设计的互斥器***************#include <boost/shared_ptr.hpp>class Mutex;class Lock{public: explicit Lock(Mutex* pm) : mutexPtr(pm, unlock) //unlock为函数删除器 { lock(mutexPtr.get()); } void ...转载 2018-07-14 00:06:30 · 109 阅读 · 0 评论 -
条款28:避免返回handles指向对象内部成分
#include <boost/shared_ptr.hpp>class Point{public: Point(int x, int y); void setX(int newVal); void setY(int newVal);private: int x; int y;};struct RectData{ Point ulhc; Point lrhc;};class Recta...转载 2018-07-14 00:06:18 · 161 阅读 · 0 评论 -
网络图片爬虫
// loadImage2.cpp: 定义控制台应用程序的入口点。//#include "stdafx.h"/*下载图片 C++ Winsock 网络编程*/#define _CRT_SECURE_NO_WARNINGS //vs 2013用于忽略c语言安全性警告#include <cstdio>#include <iostream>#include <fstre...原创 2018-07-06 17:17:17 · 590 阅读 · 0 评论 -
条款27:尽量少做转型动作
/********************************老式:(T)expressionT(expression)新式:const_cast<T>(expression); //将对象的常量性转除dynamic_cast<T>(expression); //安全向下转型, base转drivedreinterpret_cast<T>(expres...转载 2018-07-14 00:06:05 · 122 阅读 · 0 评论 -
条款26:尽可能延后变量定义式的出现时间
尽可能延后的真正意义:你不仅应该延后变量的定义直到非使用不可为止, 甚至应该偿试延迟这份定义直到能给它初始值为止。 //这样不但可以避免不必要的构造和析构,还可以避免无意义的default构造行为/******************示例void encrypt(string encrypted);string encryptPassowrd(const string& password)...转载 2018-07-14 00:05:51 · 157 阅读 · 0 评论 -
条款25:考虑写出一个不抛异常的swap函数
//*********************************************************************************swap原本只是STL的一部分,后来成为异常安全性编程(exception-safe programming)的脊柱,以及用来处理自我赋值可能性的一个常见机制/*************************************...转载 2018-07-14 00:05:38 · 110 阅读 · 0 评论 -
条款24:若所有参数皆需类型转换,请为此采用non-member函数
//令class支持隐性类型转换通常是个糟糕的主意, 但也有例外, 最常见的例外是在建立数值类型时//以有理数类(class Rational)示例:/**********************************************************************class Rational{public: Rational(int numerator = 0, int...转载 2018-07-14 00:05:26 · 109 阅读 · 0 评论 -
条款23:宁以non-member、non-friend替换member函数
/**********************************************************************//对下类提供一个清理全部的函数class WebBrowser{public: void cleanCache(); void cleanHistory(); void cleanCookies(); //1. 提供一个member函数,调用前面三个函数 ...转载 2018-07-13 10:06:33 · 334 阅读 · 0 评论 -
条款30:透彻了解inlining的里里外外
inlining函数背后的整体观念是, 将“此函数的每一个调用”都以函数本体换之。所以会增加目标码代码.inlining只是对编译器的一个申请,而不是一个强制命令。这项申请可以隐喻提出也可以明确提出。隐喻方式:将函数定义于class定义式内,这样的函数通常是成员函数,定义于class定义式内的friend函数**例:class Person{public: int age() const {ret...转载 2018-07-14 00:06:42 · 114 阅读 · 0 评论 -
条款31:将文件间的编译依存关系降至最低
//如果对C++文件进行了修改,注意只是class实现不是接口,而且只改private部分,然后重新build这个程序,有可能整个世界都被重新编译和边接了//因为C++并没有把“将接口从实现中分离”这事做得很好, Class的定义式不仅详细叙述了class接口,还包括十足的实现细目。/************************************//前置声明面临的一个困难:编译器必须在编...转载 2018-07-14 00:06:53 · 132 阅读 · 0 评论 -
条款32:确定你的public继承塑模出is-a关系
如果你令classD("Derived")以public形式继承classB("Base"),你便是告诉c++编译器,每个类型为D的对象同时也是一个类型为B的对象,反之不成立。B比D表现出更一般化的概念,而D比B表现出更特殊化的概念。public继承意味着is-a。适用于base classes身上的每一件事都适用于derived classes身上, 因为每一个derived class对象也是...转载 2018-07-14 00:07:05 · 168 阅读 · 0 评论 -
条款39:明智而审慎地使用private继承
/***********示例class Person{};class Student : private Person{};void eat(const Person& p);void study(const Student& s);Person p;Student s;eat(p); //没问题eat(s); //错误***************///规则一:private...转载 2018-07-16 08:45:03 · 220 阅读 · 0 评论 -
条款38:通过复合塑模出has-a或“根据某物实现出”
/程序中的对象,其实相当于你所塑造的世界中的某些事件,例如人、汽车、一线线画面等等,这样的对像属于应用域部分( Application domain ).//其它对象则纯粹是实现细节上的人工制品, 像是缓冲区(buffers),互斥器(mutexes),查找树(search trees)等等,这些相当于软件的实现域( Implememtation domain ).//当复合发生在应用域对象之间,...转载 2018-07-16 08:45:13 · 169 阅读 · 0 评论 -
条款37:绝不重新定义继承而来的缺省参数值
//virtual是动态绑定( dynamically bound ), 而缺省数值却是静态绑定( statically bound )/*******************************************#include <string>class Shape{public: enum ShapeColor { Red, Green, Blue }; virtual...转载 2018-07-16 08:45:23 · 150 阅读 · 0 评论 -
条款36:绝不重新定义继承而来的non-virtual函数
/********************************************class B{public: void mf();};class D : public B{public: void mf();};D x;B* pb = &x;D* pd = &x;pb->mf(); //调用的是B::mf();pd->mf(); //调用的是D::mf(...转载 2018-07-16 08:45:34 · 134 阅读 · 0 评论 -
条款35:考虑virtual函数以外的其他选择
/**Non-Virtual Interface 手法实现Template Method模式//一个有趣的流派主张:virtual函数几乎总是private, 用一个public non-virtual函数调用private(/protected) virtual函数来进行实际工作//这是Template Method模式的一个独特的表现//示例:class GameCharacter{publi...转载 2018-07-16 08:45:44 · 184 阅读 · 0 评论 -
条款34:区分接口继承和实现继承
声明一个pure virtual函数的目的是为了让derived classes只继承函数接口//我们可以为pure virtual函数提供定义, 但调用它的唯一途径是“调用时明确指出其class名称” 如: derived->Base::pureVitural();//这种方法可用于当你想提示客户“不要忘了重写某个函数,但如果真不想写允许他可以选择缺省行为”如:class Airplane...转载 2018-07-16 08:45:54 · 125 阅读 · 0 评论 -
提升 C++ 技能的 7 种方法
原文地址:http://blog.jobbole.com/112246/夏天时常会谈到大海、太阳、沙滩、大山或者你的家庭住宅。更充裕的时间也是夏天带来的好处之一。可能是因为你在休假,也可能是因为这段时间工作没有那么忙。无论是哪种情况,与一年中的其他季节相比,夏天的时间似乎更加宽裕。你有两个选择:1)把所有夏季空闲时间都用来休整,适当放松一下没什么不可以。2)或者你可以投入一部分空闲时间来提升你的技...转载 2018-07-07 16:52:02 · 566 阅读 · 0 评论 -
条款33:避免遮掩继承而来的名称
/***********************************//derived classes内的名称会遮掩base classes内的名称,示例:class Base{public: virtual void mf1() = 0; virtual void mf1(int x); virtual void mf2(); ...}class Derived : public Base{...转载 2018-07-14 00:07:16 · 99 阅读 · 0 评论 -
条款22:将成员变量声明为private
切记将成员变量声明为private, 这可赋予客户访问数据的一致性,可细微划分访问控制,约束条件获得保证,并提供class作者以充分的实现弹性protected并不比public更具封装性.一致性:用户只能访问class的函数精确控制访问权限封装:以后更改返回值的计算方式,不用更改用户接口***一旦你将一个成员变量声明为public或protected,而客户开始使用它,就很难改变那个成员变量所涉...转载 2018-07-13 00:13:59 · 81 阅读 · 0 评论 -
条款21:必须返回对象时,别妄想返回其reference
绝对不要返回pointer或者reference指向一个local stack对象。如:const Rational& operator*(const Rational& lhs, const Rational& rhs){ Rational result(lhs.n*rhs.n,lhs.d*rhs.d); return result;}这个函数返回一个refe...转载 2018-07-13 00:14:10 · 115 阅读 · 0 评论 -
条款20:宁以pass-by-reference-to-const替换pass-by-value
pass-by-value : 以实际实参的副本为初值,而调用端获得的也是函数返回值的一个副本,这些副本是由对象的copy构造函数产出,这可能使的这种方式成为费时昂贵的操作。pass-by-reference-to-const能更高效,并用可以解决对象切割问题.//切割问题class Window{public: std::string name() const; virtual void dis...转载 2018-07-13 00:14:23 · 94 阅读 · 0 评论 -
条款08:别让异常逃离析构函数
>析构函数绝对不要吐出异常.如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们或结束程序.>如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么classes应该提供一个普通函数(而非在析构函数中)执行该操作....转载 2018-07-12 17:35:45 · 71 阅读 · 0 评论 -
条款07:为多态基类声明virtual析构函数
当derived class 对象经由一个base class 指针被删除,而该base class 带着一个non-virtual 析构函数,其结果未有定义。实际执行时通常发生的是对象的derived成分没被销毁,只销毁了base class成分。解决办法:给base class 一个virtual析构函数。任何class 只要带有virtual函数都几乎确定应该也有一个virtual析构函数。...转载 2018-07-12 17:25:50 · 75 阅读 · 0 评论 -
条款06:若不想使用编译器自动生成函数,就该明确拒绝
将函数声明为private而且不定义。继承一个实现了方法1的类。转载 2018-07-12 15:50:57 · 114 阅读 · 0 评论 -
条款05:了解C++默默编写并调用哪些函数
class Empty{}相当于:class Empty{public: Empty(){...} Empty(const Empty& rhs){...} ~Empty(){...} Empty& operator=(const Empty& rhs){...}};如果赋值操作中的行为与C++的允许操作行为相冲突,则C++会拒绝编译这一行为,如:C...转载 2018-07-12 15:41:31 · 78 阅读 · 0 评论 -
条款04:确定对象被使用前已先被初始化
永远在使用对象之前先将它初始化。对于无任何成员的内置类型,必须手工完成此事。确保每一个构造函数都将对象的每一个成员初始化。对象成员变量的初始化动作发生在进入构造函数本体之前。在本体不是被初始化,而是被赋值。可以使用成员初始化列表来实现初始化操作。C++固有的“成员初始化次序”,base classes早于derived classes被初始化。class的成员变量总是以其声明次序被初始化。C++对...转载 2018-07-12 15:24:41 · 110 阅读 · 0 评论 -
条款03:尽可能使用const
const指定一个语义约束,而编译器会强制实施这项约束。面对指针,如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量。STL迭代器的作用就像T*指针。可用const_iterator模拟一个const T*指针:std::vector<int>vec;...const std::vector<int>::iterator iter...转载 2018-07-11 19:10:22 · 80 阅读 · 0 评论 -
条款02:尽量以const,enum,inline替换#define
#define不被视为语言的一部分。#define ASPECT_RATIO 1.653ASPECT_RATIO也许从未被编译器看见;也许在编译器开始处理源代码之前它就被预处理器移走了。所以ASPECT_RATIO有可能没进入记号表(symbol table)内。当发生编译错误时会带来困惑。如果ASPECT_RATIO被定义在一个非你所写的头文件内,追踪起来会浪费时间。解决方法:const dou...转载 2018-07-11 17:44:43 · 120 阅读 · 0 评论 -
条款01:视C++为一个语言联邦
为了理解c++,你必须认识其主要的次语言:C 。C++是以C为基础。Object-Oriented C++。Template C++。STLC++高效编程守则视状况而变化,取决于你使用C++的哪一部分。...转载 2018-07-11 16:05:32 · 113 阅读 · 0 评论 -
条款09:绝不在构造和析构过程中调用virtual函数
补偿做法:>由于你无法使用virtual函数从base classes向下调用,在构造期间,你可以藉由"令derived classes将必要的构造信息向上传递至base class构造函数"替换之而加以弥补.请记住:>在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class(比起当前执行构造函数和析构函数的那层)....转载 2018-07-12 17:49:59 · 100 阅读 · 0 评论 -
条款10:令 operator=返回一个reference to *this
连续赋值x=y=z=15相当于x=(y=(z=15))所以为了实现连续赋值需要返回一个reference实参指向操作符左侧实参.通常做法:class Widget{public:... Widget& operator=(const Widget& rhs) { .... return* this; }....};+=,*=,-=等同....转载 2018-07-12 17:56:13 · 150 阅读 · 0 评论 -
条款11:在operator=中处理"自我赋值"
自我赋值:w=w (合法)潜在的自我赋值:a[i]=a[j] i和j有相同的值*px=*py; px和py指向同一个东西rb 和 *pb 可能其实是同一个对象class Base{...};class Drived: public Base{..};void doSomething(const Base& rb, Drived* pb){...}================...转载 2018-07-12 18:28:48 · 120 阅读 · 0 评论 -
条款19:设计class犹如设计type
Class的设计就是type的设计。1、新type的对象应该如何被创建和销毁2、对象的初始化和对象的赋值该有什么样的差别3、新type的对象如果被passed by value(以值传递),意味着什么?记住,copy构造函数用来定义一个type的pass-by-value该如何实现。4、什么是新type的”合法值“5、你的新type需要配合某个继承图系吗?6、新的type需要什么样的转换?7、什么...转载 2018-07-13 00:14:32 · 73 阅读 · 0 评论 -
条款18:让接口容易被正确使用,不易被误用
//! 易出错的接口定义class Date{public: Date(int month, int day, int year); ...};Date d(30, 2, 1985);Date d(2, 30, 1984);//! 优化的接口定义struct Day{explicit Day(int d):val(d){}...};struct Month{explicit Month(int d...转载 2018-07-13 00:14:43 · 76 阅读 · 0 评论 -
条款17:以独立语句将newed对象置入智能指针
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());编译器创建代码做以下三件事:1. 调用priority()2. 执行new Widget3. 调用shared_ptr构造函数C++不同于很多语言,C++完成上面的事的顺序可能是123,213, 231.如果顺序是213,那么当priority发生异常...转载 2018-07-13 00:15:05 · 89 阅读 · 0 评论 -
条款16:成对使用new和delete时要采取相同形式
//错误的示例:std::string stringArray = new std::string[100];...delete stringArray;当你使用new,有两件事发生。第一,内存被分配出来(通过名为operator new的函数)第二,针对此内存会有一个(或更多)构造函数被调用。当你使用delete,也有两件事发生:针对此内存会有一个(或更多)析构函数被调用内存被释放(通过oper...转载 2018-07-13 00:15:15 · 108 阅读 · 0 评论 -
条款15:在资源管理类中提供对原始资源的访问
shared_ptr和auto_ptr都提供一个get成员函数,用来执行显示转换,返回智能指针内部的原始指针(复件):int days=daysHeld(pInv.get());shared_ptr和auto_ptr也重载了指针取值操作符(operator->和operator*),允许隐式转换至底部原始指针:class Investment{public: bool isTaxFre...转载 2018-07-13 00:14:56 · 109 阅读 · 0 评论 -
条款14:在资源管理类中小心coping行为
/***************************************************************************class Mutex;class Lock{public: explicit Lock(Mutex* pm) : mutexPtr(pm) { lock(mutexPtr); } ~Lock() { unlock(mutexPtr); }p...转载 2018-07-13 00:15:54 · 130 阅读 · 0 评论