`

放假了,n长时间没有用过c++的class了,回顾一下.

阅读更多
1、你的类需要构造函数么?
对于一个复杂的类,我们要隐藏掉复杂的细节,而让用户看到一个简洁的界面,
构造函数对于隐藏内部的工作方式非常重要,因为他设定了整个程序的初始状
态,我们只把需要由用户设定的数据,作为参数,让他们来初始化为恰当的值
而其他我们都有一个默认的设置,这就隐藏掉了内部的细节。我们甚至需要思
考这个类是能产生单个实例还是多个,这就需要我们思考是否应该将构造函数
私有。


2、你的那些数据应该私有?
通常使用公有的数据成员不是个好事,因为将失去对这个数据对象的控制,使用
者可以随意修改这个值,而我们又无法在这个更改的过程中提供一个有效的合法
检查机制,同时我们也无法提供一个检测到这种更新的方法从而同时保证与之相
关联的数据得到及时的更新。下面我们思考一下容器向量类设计:
template<class T>
class Vector
{
 public:
   int length;
 private:
  T *v;
};

如果我们把length的长度声明为公有的,我们将无法保证当前的length是否真正的反
映了当前Vector的实际大小。我们同样也无法保证这个值是否在合法的范围之内。因
为我们无法知道使用者何时访问length变量、是否修改这个变量以及如何修改这个变
量,我们即使检测到length的变化,而这个变化也是滞后的,甚至是不可预料的,我
们就无法及时的更新的Vector的容量。所以我们这么设计:
template<class T>
class Vector
{
public:
 int get_length()const;
 void set_length(int len);
private:
 int length;
 T *v;
};

我们可以在set_length()函数中提供合法的范围检查以及及时地更新与之相关的数据。


3、你的类需要一个无参的构造函数么?
如果一个类有了其他的构造函数,而你又想申明一个不需要显式初始化的对象,则必须
需要一个无参的构造函数,这样的对象有时你会忽视。以为你可能是有意这么做的,但
你必须考虑到,当这个类试图生成一个对象数组时,所要面临的问题。
例如:
class Point
{
 public:
  Point(int x_Pos,int y_Pos):x(x_Pos),y(y_Pos)
  {
  }
 private:
  int x,y;
};

当我们试图生成该类的对象数组时,却是非法的。
Point p[200];

虽然对一个大的对象,定义一个对象数组,导致大量对象的初始化,可能要付出性能的代价,
但必须要权衡是否因此而禁止对象数组。


4、是否要初始化所有的数据成员:
构造函数的功能,就是初始化生成对象的状态。对象的状态是由他的数据成员反映的。因此,
构造函数为每个数据设置一个合理的初值是必要的,如果没有做到这一点,就可能导致错误。
当然,有时,一些数据的值只有在对象存在一段状态之后才有意义,这时候需要你思考设置
一个什么样的初值。


5、类需要析构函数么?
对于一个简单的类,只需要默认的析构函数,如果要深入考虑一个类的要做些什么,那么是否
需要析构函数是一个很明显的问题了。只需要考虑你是否new了一些资源,而这些资源不会自动
释放就足够了。


6、类需要虚析构函数么?
当然如果你的类不是用作基类的,当然不需要考虑虚析构函数的问题。下面我们看看,虚析构函
数的使用:
class A
{
 //...
};
class B: A
{
 //...
};
int main()
{
 A *ap = new B;
 delete ap;
 return 0;
}

只这里如果没有虚析构函数就会出现问题,可见作为基类一个虚析构函数是非常重要的,因为我们
经常用基类的指针去指向他的子类的对象。


7、你的类需要深拷贝构造函数么?
  如果一个类复制仅仅是想简单的拷贝其数据成员,那就不需要。但有时是需要的,例如类
String
Class String
{
public:
 String();
 String(const char* s);
 ~String();
private:
 char *data;
};

如果没有深拷贝构造函数的话,复制String对象就是简单复制他们他的data成员,复制完后,两个data
成员就会指向同样的内存,当两个对象被销毁的时候,这个内存就会被释放两次。
  有时候你可能会禁止使用者复制一个类对象,这往往是出于性能的考虑,为了禁止用户不当的使用。
例如:
class SomeThing
{
public:
  //...
private:
  //许多的数据成员;
};

如果你允许复制,使用者总会无意的在不恰当的时机使用这项功能,例如:
void func(SomeThing st){}
这往往是给了使用者不恰当使用的机会。如果你禁用复制这个功能,他就会想,哦,这样做不合适,就会写出: void func(SomeThing &st){}
这里我们只需要将拷贝构造函数私有(可能还有赋值操作符号):
class SomeThing
{
 public:
  //...
 private:
  SomeThing(const Thing&);
  SomeThing &operator=(const Thing&);
};

当然,除了一个很大的对象的复制行为给予禁止,大多数类我们不会这么做。


8、你的类需要一个赋值操作符么?
如果你需要一个拷贝构造函数的时候,大多会需要赋值操作符类,许多人会把赋值操作的原型搞错
类String的原型为:
String::String &operator=(const String&)
{
 if(&s != this)
  {
     delete []data;
     date = new char[ strlen(s.data)+1 ];
     strcpy(data,s.data);
   }
   return *this;
};

这里的参数是const的,这么做的理由是:1)复制毕竟不改变原来的对象;2)使用const更具有通用性,
如果没有const你就无法去复制一个const对象,而如果加上const则不仅可以复制const对象,一般的对象
也同样胜任。这点在拷贝构造函数中也是一样的。许多人写的时候就会漏写if的判断,似乎自己赋值给对象本身不是什么严重错误。但是由于:
1)自我赋值本身就是一个无意义的操作;2)由于上述的实现方式,在赋值拷贝之前已经把自身delete掉
了,所以在没有实施复制之前就把原对象销毁了。


9、你需要定义关系运算符么?
如果你在逻辑上支持operator==和operator!=就可能会很有好处,类似的你的类中有某些排序关系,那么你还需要提供类似operator>,operator<之类的操作符,即使你不想让用户直接使用关系符,只要你想创建你的类型的有序集合,你就必须提供关系操作符.


10、适当的声明成员函数为const的。
例如前面的例子:
template<class T>
class Vector
{
 public:
  int get_length()const;
  //...
};

如果我们不把get_length声明为const,就会遇到下面问题:
int f(const Vector<T>& v,int n)
{
 int k = v.length();
 return k > n ? k : n; 
}

如果get_length()不是const的话,v.length()就会出现问题。
总结:设计一个c++的类需要考虑许多东西,而不想java。换言之,c++更适合喜欢思考的程序员。



分享到:
评论
1 楼 healer_kx 2008-07-14  
其实我想评价你其他的C++文章。

相关推荐

    Dev C++ 5 V4.9.9.2免费版.exe

    Dev C++ 5 V4.9.9.2免费版.exe Dev C++ 5 V4.9.9.2免费版.exe Dev C++ 5 V4.9.9.2免费版.exe Dev C++ 5 V4.9.9.2免费版.exe

    冒泡91.cpp 使用的C++实现

    冒泡91.cpp 使用的C++实现冒泡91.cpp 使用的C++实现冒泡91.cpp 使用的C++实现冒泡91.cpp 使用的C++实现冒泡91.cpp 使用的C++实现冒泡91.cpp 使用的C++实现冒泡91.cpp 使用的C++实现冒泡91.cpp 使用的C++实现冒泡91....

    C++的文件 windows.h头文件

    C++的文件 windows.h头文件

    C++标准库(第二版)英文版.pdf

    The C++ Standard Library A Tutorial and Reference (2nd Edition)+cppstdlib-code.zip C++标准库(第二版)英文版.pdf 非扫描版+源代码 Prefaceto the SecondEdition xxiii Acknowledgments for the Second...

    C++面试题集.pdf

    C++面试题集.pdf 本文档提供了一系列C++面试题,涵盖了内存拷贝、双向链表、费波那其数列、类的构造函数、析构函数和赋值函数、循环、单向链表类的实现、二叉树实现等多个方面的知识点。 内存拷贝 面试题:写一个...

    一个小小的从c++程序class.cpp

    一个小小的从c++程序class.cpp

    c++class-doc.chm

    Mastering The Standard C++ Classes: A Tutorial and Reference

    7本经典C++教程PDF打包.rar

    C++是一种强大的、通用的编程语言,以其高效性、灵活性和面向对象的特性而闻名。这个压缩包"7本经典C++教程PDF打包.rar"包含了七本深入学习C++的教程,是提升C++技能的理想资源。以下是这些教程可能涵盖的一些关键...

    C++开发及调用.OCX文件

    这篇文档"OCX开发及调用"将指导你如何在Visual Studio 2013环境下进行C++ OCX控件的开发和使用。 首先,了解OCX控件的基础。OCX(旧称OLE控件)是基于COM(Component Object Model)的,它允许开发者创建小型、自...

    C++基础入门.md.pdf

    C++编程语言包含大量的关键字,如`if`、`else`、`while`、`for`、`switch`等控制语句关键字,以及`class`、`struct`、`enum`等面向对象编程关键字。C++的关键字是区分大小写的,例如`int`和`Int`会被视为两个不同的...

    四国军棋源码C++......

    本源码是用C++语言编写的,对于初学者和希望深入理解C++编程以及游戏开发的程序员来说,这是一个很好的学习资源。下面我们将详细探讨这个四国军棋源码中的关键知识点。 首先,C++是一种面向对象的编程语言,它在...

    堆排序11.cpp 使用C++实现

    堆排序11.cpp 使用C++实现堆排序11.cpp 使用C++实现堆排序11.cpp 使用C++实现堆排序11.cpp 使用C++实现堆排序11.cpp 使用C++实现堆排序11.cpp 使用C++实现堆排序11.cpp 使用C++实现堆排序11.cpp 使用C++实现堆排序11...

    王桂林老师 c++基础与提高.pdf

    王桂林老师编写的《C++基础与提高》是一本系统讲解C++编程语言的书籍,其中详细介绍了C++的发展背景、应用领域以及与C语言相比扩展出的新特性。以下是根据书中内容整理出的详细知识点: 1. C++的综述:C++由Bjarne ...

    C++帮助手册文档.chm

    C++帮助手册文档.chm c++ 参考手册

    C++基础入门.pdf

    C++关键字包括auto、break、case、catch、char、class、const、continue等。这些关键字不能用于定义变量或常量的名称。 1.6 标识符命名规则 C++规定了标识符(变量、常量)的命名规则。标识符不能是关键字,且只能...

    C++学习笔记......

    C++是一种通用的编程语言,由Bjarne Stroustrup在C语言的基础上发展而来,它在1983年首次引入。C++以其强大的面向对象编程能力、性能优化以及对系统级编程的支持而闻名。本学习笔记将深入探讨C++的基础、核心概念...

    C++test v6.0.0.5破解版(1)

    C++test v6.0.0.5破解版 安装完后需替换一文件,才能使用 仅测试,可以使用 这个软件有点大,所以打了三个包

    树状数组2.cpp 使用C++实现

    树状数组2.cpp 使用C++实现树状数组2.cpp 使用C++实现树状数组2.cpp 使用C++实现树状数组2.cpp 使用C++实现树状数组2.cpp 使用C++实现树状数组2.cpp 使用C++实现树状数组2.cpp 使用C++实现树状数组2.cpp 使用C++实现...

    Microsoft Visual C++ 2013 Redistributable Package 12.0.40660(32/64).zip

    它主要服务于那些使用Visual Studio 2013开发环境编译的程序,确保这些程序在没有安装完整Visual Studio的计算机上也能正常运行。 C++ 是一种强大的、通用的编程语言,被广泛用于系统软件、游戏开发、桌面应用、...

Global site tag (gtag.js) - Google Analytics