一、系统跟踪类Trace的设计过程:

step1:简单版

class Trace
{
public:
Trace()
{
noisy = ;
} void print(char* s)
{
if(noisy)
print("%s", s);
} void on()
{
noisy = ;
} void off()
{
noisy = ;
} private:
int noisy;
};

step2:增加重定向功能,可能输出到别的文件中。

class Trace
{
public:
Trace()
{
noisy = ;
f = stdout;
} Trace(FILE *ff)
{
noisy = ;
f = ff;
} void print(char* s)
{
if(noisy)
fprintf(f, "%s", s);
} void on()
{
noisy = ;
} void off()
{
noisy = ;
} private:
int noisy;
FILE *f;
};

步骤二的改动,基于这样一个事实:

  printf(args);

  等价于:

  fprintf(stdout, args);

二、类设计者的核查表

  1. 你的类需要一个构造函数吗?

  足够复杂的类需要构造函数来隐藏它们的内部工作方式。

  2. 你的数据成员是私有的吗?

  通常,使用公有的数据成员不是什么好事,因为类的设计者无法控制对这些数据成员的访问。

  3. 你的类需要一个无参构造函数吗?

  如果一个类有了构造函数,而你想声明该类对象的时候不必显示地初始化它们,则必须显式地写一个无参构造函数。

  例如:

class Point
{
public:
Point(int p, int q): x(p), y(q)
{ }
//... private:
int x, y;
}; Point p; //错误,没有合适的默认构造函数可用
Point q[100]; //错误,没有合适的默认构造函数可用

  4. 是不是每个构造函数初始化所有的数据成员?

  如果没有初始化所有的数据成员,很容易出现难以发现的错误。

  5. 你的类需要析构函数吗?

  注意:并不是所有存在构造函数的类都需要析构函数。

  需要不需要析构函数,主要在于该类是否分配了资源,而这些资源又不会伴随成员函数而自动释放。特别是那些在构造函数中有 new 操作符的类,通常要在析构函数中用 delete 来释放相对应的资源。

  •   6.你的类需要一个虚析构函数吗?
  •   注意:当一个类用于不会被继承时,这个类是不需要虚析构函数的。
class Base
{
public:
Base()
{
s = "";
} private:
string s;
}; class Dase : Base
{
public:
Dase()
{ }
private:
string t;
}; int main()
{
Base *b = new Dase();
delete b;//除非Base有一个虚析构函数,否则将调用错误的析构函数
}

  7你的类需要一个复制构造函数吗?

  什么时候需要一个复制(拷贝)构造函数呢,正如在 何时需要自定义复制构造函数?里所说的,

  当类中的数据成员需要动态分配存储空间时,不可以依赖默认的复制构造函数。在需要时(包括这种对象要赋值、这种对象作为函数参数要传递、函数返回值为这种对象等情况),要考虑到自定义复制构造函数。另外,复制构造函数一经定义,赋值运算也按新定义的复制构造函数执行。

  下面,我们再举一个例子:

class CString
{
public:
CString();
CString(const char * s)
{ }
//other function private:
char *data;
};

  我们可以知道,在构造函数中需要对数据成员 data 进行内存的动态分配,因此,类CString 需要一个析构函数,同理,它也需要一个显式的复制构造函数,如果没有的话,复制CString对象就会以复制它的 data 成员的形式隐式地定义,复制完成后,两个对象的 data 成员同时指向了同一个内存块,当这两个对象被销毁时,data 会被释放两次,这显然不是我们想要的。

  但如果不想用户能够复制CString 类的对象,可以定义复制构造函数(可能还有赋值操作符)为私有的。如下:

class CString
{
public:
CString();
CString(const char * s)
{ }
//other function private:
char *data; CString(const CString&);
CString& operator= (const CString&
);
};

实现如下:

CString(const CString& s)
{
data = new char(strlen(s.data) + );
strcpy(data, s.data);
}

  8. 你的类需要一个赋值操作符吗?

  如果你的类需要复制构造函数,多半也需要赋值操作符,实现如下:

CString& operator= (const CString& s)
{
if(&s != this)
{
delete [] data;
data = new char(strlen(s.data) + );
strcpy(data, s.data);
}
return *this;
}

  9. 你的赋值操作符能正确地将对象赋值给对象本身吗?

  10. 你的类需要定义关系操作符吗?

  操作符的重载。

  11. 删除数组时你记住用 delete [] 了吗?

  内存的正确管理。

  12. 记得在复制构造函数和赋值操作符的参数类型中加上 const 了吗?

  有些C++的早期著作建议类 X 的复制构造函数的形式写成: X::X(X&)。这种建议是不正确的。

  复制构造函数的形式应该写成如下:

  X::X(const X&);     注意不同

  毕竟复制对象不会改变原对象的值。

  同理,这个也适合 重载操作符=。应该写成:

  X& operator= (const X&);

  13. 如果函数有引用参数,它们应该是const引用吗?

  14. 记得适当地声明函数为 const 的了吗?

C++沉思录之一的更多相关文章

  1. 【C++沉思录】句柄2

    1.[C++沉思录]句柄1 存在问题: 句柄为了绑定到Point的对象上,必须定义一个辅助类UPoint,如果要求句柄绑定到Point的子类上,那就存在问题了.2.有没有更简单的办法呢? 句柄使用Po ...

  2. 【C++沉思录】句柄1

    1.在[C++沉思录]代理类中,使用了代理类,存在问题: a.代理复制,每次创建一个副本,这个开销有可能很大 b.有些对象不能轻易创建副本,比如文件2.怎么解决这个问题? 使用引用计数句柄,对动态资源 ...

  3. 生活沉思录 via 哲理小故事(四)

    1.围墙里的墓碑 第一次世界大战期间,驻守意大利某小镇的年轻军官结识了镇上的牧师.虽然军官信仰信教,而牧师是天主教牧师,但两人一见如故. 军官在一次执行任务中身负重伤,弥留之际嘱托牧师无论如何要把自己 ...

  4. 生活沉思录 via 哲理小故事

    本文转载:http://www.cnblogs.com/willick/p/3174803.html 1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛, ...

  5. 生活沉思录 via 哲理小故事(一)

    1.小托蒂的悲剧 意大利小男孩托蒂,有一只十分奇怪的眼睛,因为从生理上看,这是一只完全正常的眼睛,但却是失明的. 原来,托蒂刚出生时,这只眼睛轻度感染,曾用绷带缠了两个星期.这对常人来说几乎没有人任何 ...

  6. Atitit。 沉思录 与it软件开发管理中的总结 读后感

    Atitit. 沉思录 与it软件开发管理中的总结 读后感 1. <沉思录>,古罗马唯一一位哲学家皇帝马可·奥勒留所著 2 2. 沉思录与it软件开发管理中的总结 2 2.1. 要有自己的 ...

  7. C++模板沉思录(上)

    花下猫语: 在我们读者群里,最近出现了比较多关于 C++ 的讨论,还兴起了一股学习 C++ 的风气.樱雨楼小姐姐对 C++ 的模板深有研究,系统地梳理成了一篇近 4 万字的文章!本文是上篇,分享给大家 ...

  8. C++模板沉思录

    0 论抽象--前言 故事要从一个看起来非常简单的功能开始: 请计算两个数的和. 如果你对Python很熟悉,你一定会觉得:"哇!这太简单了!",然后写出以下代码: def Plus ...

  9. 【C++沉思录】代理类

    1.考虑下面的场景:设计一个容器,包含一组类型不同但相互关联的对象(比如:Animal,Dog,Cat),对象具备多态行为.2.容器一般只能包含一种类型的对象,使用vector<Animal&g ...

  10. OOD沉思录 --- 类和对象的关系 --- 包含关系4

    4.9 在实现语义约束时,最好根据类定义来实现.但是这经常会导致泛滥成灾的类,在这种情况下约束应当在类的行为中实现,通常在类的构造函数中实现,但不是必须如此. 还是以汽车为例,我们看汽车的定义,为了集 ...

随机推荐

  1. vsftp关于"550 create directory operation failed"问题解决

    前提: 昨天晚上配置好了vsftp, 但登陆后,除了浏览,什么也干不了.(如新建文件/文件夹, 删除文件, 重命名等都不可操作) 都是弹出 "550 create directory ope ...

  2. CSS中的盒子模型详解

    很多人对盒子模型搞晕头了,下面通过一个简单的代码来分析盒子模型的结构! 为了方便方便观看!在第一个div中画了一个表格,并将其尺寸设置成与div内容大小一样!且设置body的margin和paddin ...

  3. Probably at least one of the constraints in the following list is one you don't want.

    这个提示并不是出错,不理会它我的程序也没出现什么问题 但是处于强迫症,还是努力寻找解决的方法... 最终发现问题如下: 在xib各种绘制和添加约束的UITableViewCell之后,在某一特定情况想 ...

  4. JavaScript 函数之 ------------------ 闭包

    谈到闭包,人们常常会把匿名函数和闭包混淆在一起.闭包是指由权访问另一个函数作用域中的变量的函数.创建闭包的常见方式,就是在一个函数内部创建另一个函数,仍以前面的 createComparisonFun ...

  5. 请写一个C函数,判断处理器是大端存储还是小端存储,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1

    [解答] int checkCPU() { { union w { int a; char b; }c; c.a=1; return (c.b==1); } } [剖析] 嵌入式系统开发者应该对Lit ...

  6. CentOS 7 之Shell学习笔记

    脚本是个永恒的话题,以前Dos下面也有Shell编程这一说的,比如说BAT文件有人写的好的话,也是瞬间速度变高大上.Linux下面这个应该更占比重了.我看到园子里有位园友做了一个Linux Shell ...

  7. Win+PHP+IECapt完整实现网页批量截图并创建缩略图

    最近在开发一个本地互联网应用的项目,为了增加用户体验,需要在搜索结果左侧显示如图一所示的某个网站的缩略图效果,在网上不停地百度谷歌了一上午后,发现大多数实现少量截图还是可以的,如果大批量的截图总会在中 ...

  8. UIScrollView 滚动停止的时候一次调用此方法

    //拖动返回选中的索引 当滚动视图停止时的时候 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ CGFloat wid ...

  9. linux运维面试题汇总一

    1.如何让history历史命令显示命令使用的具体时间? [root@node0 ~]# export HISTTIMEFORMAT='%F  %T ' [root@node0 ~]# history ...

  10. Python自动化运维之7、生成器、迭代器、列表解析、迭代器表达式

    迭代器和生成器 1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外 ...