条款专题

More Effective C++ 条款04:非必要不提供默认构造函数

所谓默认构造函数,就是不给任何变量,就可以给调用(无参或参数为默认值)。 基本准则:凡可以“合理地从无到有生成对象”的类,都应该包含默认构造函数,而“必须有某些外来信息才能生成对象”的类,则不必拥有默认构造函数。 但如果类缺乏一个默认构造函数,当你使用这个类时便会有某些限制。 考虑下面这个针对公司仪器而设计的class,在其中,仪器识别码是一定得有的一个构造参数: class Equipm

effective C++条款27,28

27. 尽量少做转型动作 c++的设计目标之一是,保证“类型错误”绝不可能发生。即,如果我们的程序能顺利的通过编译,那么就意味着它一定不会在任何对象身上出现任何不安全的操作。 在大部分情况下,转型会破坏我们原有的类型系统,有可能会产生一些很隐晦的错误,所以我们需要慎重选择转型操作,尽量通过设计来避免转型 类型转换的底层工作 任何的一次类型转换,编译器都会编译出运行时期执行的码。 i

Effective C++ 条款41

本节条款对比了一下两对概念的对比。 首先是 编译期多态和运行期多态。 接着是 显示接口和隐式接口 编译期多态是由于模板而产生的。 如下代码: #include<iostream>using namespace std;class Bird{public:Bird(int v):value(v){}int getSize(){ return value; }private:int

Effective C++条款40

本节条款讲述了多重继承的使用 多重继承一般情况下用的很少,原因在于多重继承容易出现程序错误。以下去两个典型的调用错误: 第一种错误如下代码: #include<iostream>using namespace std;class B{public:virtual int m(){}};class C {public:virtual int m(){};};class D :pu

Effective C++ 条款39

我从本条款中学到了以下内容: 1.private继承不同于另外两种继承,派生类对象不能隐式转换为基类对象。如下代码: class Bird//鸟{};class ostrich:private Bird//鸵鸟{};int main(){Bird *b = new ostrich();//编译不通过,基类不能转换为派生类} 编译器明确指出基类是不可访问的,所以转换失败。privat

Effective C++ 条款38

本节条款相对简单,通俗的意思就是说 “有一个”和“是一个”的区别,以及在应用域(application domain)和实现域之间的区别(implementation domain)。 如下代码: 1. class Bird//鸟{public://............};class ostrich:public Bird//鸵鸟{public://............}

Effective C++条款37

不要重复定义virtual 函数中的参数缺省值,如果重复定义,会出现程序调用过程超乎常理的结果。 大家看如下代码: #include<iostream>using namespace std;class Shape{public:enum ShapeColor{Red,Green,Blue};virtual void Drew(ShapeColor color=Red){if (colo

Effective C++ 条款36

本节条款相对容易,作者原意是说在base class 中定义的non-virtual函数,不应该在derived class中重复定义。如果重复定义会掩盖base class中的同名函数。换句话说,你在base class中的函数定义不但没有意义,反而会在多态调用过程中出现很大的逻辑问题。 如下代码: #include<iostream>using namespace std;class P

Effective C++ 条款35

本条款作者所要表达的用意就是对于virtual成员函数的功能实现可以以其他形式代替。有的时候单纯的virtual函数可能无法满足真实编程的需要。 第一种方法: 定义一个private virtual函数,再定义一个non-virtual函数,non-virtual函数调用private virtual函数实现功能。 代码如下: class person{public:virtual

Effective C ++ 条款34

该条款讲的内容就是以下3点: 第一点: pure virtual 成员函数的作用,纯虚函数的作用就是base class基类提供给derived class 派生类一个接口,而且只是起到接口的目的。 举到例子, class picture{public:virtual void Drew()=0;};class picture1:public picture{public:virtu

Effective C++ 条款33

本条款讲的是关于同名的变量或函数在继承体系中的调用问题。 如下例子: class Base{public:virtual void mf1();virtual void mf1(int);virtual void mf2();void mf3();void mf3(int);void mf4();};class Derived: public Base{public:virtual vo

Effective C++ 条款5

了解C++默认编写并调用哪些函数 本节有两处知识点。 首先 对于一个class 1.如果class中没有任何构造函数,那么编译器为class声明一个default默认构造函数。 2.如果class没有析构函数、copy构造函数、copy assignment运算符则class声明这三个函数。 3.只有当调用析构函数、copy构造函数、copy assignment运算符时,编译器才生成

Effetive C++ 条款4

确定对象使用前已先被初始化 我们都明白如果程序中使用了未经初始化的数据成员,那么程序将会出现非预期的错误结果。 本节就是说明如何初始化的一般方法 首先 对于一个class来说,它的初始化使用成员初始化列进行,构造函数中所谓的“初始化”是赋值。如下,前者是初始化后赋值,后者是直接初始化。 class P{public:P(int x0, int y0){x=x0;y=y0;}priva

Effective C++ 条款3

尽可能使用const const关键字在编程中的应用广泛,如何灵活的发挥它的优势值得我们探讨, 首先 理解什么是const,如何使用const。 我们看一下对于一个指针有关const的应用。 char g[]="hello";char *p=g;const char *p=g;//该指针指向的数据不可修改char *const p=g;//该指针自身的值不能修改const cha

Effective C++ 条款2

尽量以const、enum、inline替换#define 首先,大家要明白一个道理。#define是什么,有什么作用。很简单,大家都知道#define实现宏定义,如下代码: #define Flag 10 以后Flag的地方,预处理器都用10来代替,试想一下,如果你的函数中不小心定义了一个Flag,而你的用意只是一个局部变量,那么程序会出现什么问题 #define Flag 10#in

Effective C++ 条款1

视C++为一个语言联邦 本节是Effective C++这本书的第一节,内容就是对C++语言的特性的描述,其实C++的特性是多样的,它不同于java,java是纯正的面向对象语言,而对于C++来说,面向对象只是其中一个主要的特征。 C++实在C的基础上发展而来,C++是兼容C的特征,C是面向结构化的语言,它的侧重点在于算法和数据结构。编写C代码,侧重点在于通过输入数据,设计一定的算法过程,得到

Effective C++ 条款54-55

条款54:让自己熟悉包括TR1在内的标准程序库 本书中的C++规范是在1998年制定的。现在C++11,即C++0x已经制定,且C++14在讨论中。本条款讨论内容是关于Boost库的,当时没有制定新标准,一些语言上的新特性以技术报告内容程序给大家,TR1代表Technical Report 1。 现在来看一下C++98加如的标准程序库有哪些: STL,即Standard Template L

Effective STL 条款15-16

条款15: 记住string实现的形式的多样性,即string的数据结构不是单一的,sizeof(string)的大小在不同的版本中是不同的。 实际上每个string实现都容纳了下面的信息: 1:包含字符的数目 2:容纳字符的容量 3:构成字符串的字符 4:配置器的拷贝 5:这个值的引用计数 本节的核心主旨就是string实现的多样性 条款16:如何将vector和string兼

Effective STL 条款14

使用reserve来避免不必要的重新分配 本节讲解reserve操作的优势,以及重新分配的代价 先来讲一下重新分配的代价: 1.分配新的内存块,一般vector和string是成倍增加内存 2.把所有元素从容器的旧内存拷贝到它的新内存 3.销毁旧内存对象 4.回收旧内存 可以看出,重新分配内存的操作是非常耗时的。 接着,解释一下以下几个迭代器函数的功能: 1.size告诉你容器中

Effective STL 条款12

对STL容器线程安全性的期待现实一点 本节讲解STL容器对于线程安全性的知识。 STL容器中明确规定有两条: 1:多线程可以同时安全读取同一个容器。 2:多线程可以同时写入不同容器。 以上两条就是STL对容器仅有的线程方面的说明。第一条的意思是说对于同一个容器,可以满足多个使用者同时读取。第二条的意思是不同的容器可以被同时写入,也就是不同容器之间并没有关联性。 现在的多线程的程序越来越

Effective STL 条款9

在删除选项中仔细选择 本节核心内容: 如何高效的删除容器中的指定数据 结论如下: 1.去除一个容器中有特定值的所有对象 如果容器是vector,string或者deque,使用erase-remove惯用法。 如果容器是list,使用list::remove 如果容器是标准关联容器,使用它的erase成员函数 2:去除一个容器中满足一个特定判定式的所有对象: 如果容器是vecto

Effective STL 条款8

永不建立auto_ptr的容器 首先,我们应该明白什么是auto_ptr,其实auto_ptr你可以认为是一种类型容器,auto_ptr类型容器有什么特点呢? 当你拷贝一个auto_ptr的时候,auto_ptr所指对象的所有权被转移到拷贝的auto_ptr对象,而被拷贝的auto_ptr被自动设为NULL. 如下代码: auto_ptr<widget>pw1(new widget);au

Effective STL 条款7

使用容器的时候 ,要避免内存泄露 众所周知,使用容器的好处是我们不用考虑容器的内存问题,容器本身具有自动内存管理的能力,包括动态申请内存和释放内存。 但是,当你存储的对象是指针的时候,你就要注意内存的人工释放了。 如下代码: void doSomething(){vector<Widget*>vwp;for(int i=0;i<num;i++){vwp.push_back( new Wi

Effective STL 条款6

本节的重点是有关C++语句解析的讨论 看一段代码: 1:int f(double d);2:int f(double (d));3:int f(double); 上面的三种函数声明的形式有区别吗? 回答没有,对的,当然没有,只不过形式不同而已。 再看下面这个片段 class A{....};A a(); 请问上面片段中的a是类对象还是返回一个类A类型的函数? 答案是难以判定

Effective STL 条款5

尽量使用区间成员函数代替它们的单元素兄弟 本节重点论述区间成员函数的优势. 首先,我们需要知道什么是区间成员函数,区间成员函数如下举例: insert(v1.begin(),v2.begin(),v2.end())assign(v1.begin(),v2.begin(),v2.end())erase(v1.begin(),v2.begin(),v2.end()).... 那什么是它的单元素

Effective STL 条款4

STL作为标准模板库,是程序员开发的利器,但是,在使用的过程中会因为使用不当,降低STL的效率。 本节就是一个简单的效率讨论,很简单,对于序列容器来说,如果你的目的是判断一个容器对象中是否有元素,有两种方法。分别如下: 方法一: container a;if(0==a.size()) 方法二: container a;if(a,empty()) 那么,相对来说,这两个语句之间的区别在