`

放假了,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++文章。

相关推荐

    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++基础入门.md.pdf

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

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

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

    class_query.rar_C++ class

    标题 "class_query.rar_C++ class" 暗示这是一个基于C++编程语言的项目,主要涉及类(class)的概念,可能是一个用于管理学生班级成绩排名的系统。描述中提到的“班级成绩排名系统测试版”确认了这个项目的功能,即...

    C++ xuhanshu.zip_C++_C++xuhanshu_c++ class xuhanshu_c++ xuhanshu

    这个压缩包文件"**C++ xuhanshu.zip**"包含了关于C++中虚函数使用的一些编程示例,这对于我们理解和掌握这一核心概念非常有帮助。 首先,我们需要理解什么是虚函数。在C++中,当一个基类指针或引用指向其派生类的...

    Dev-C++ 6.0(更名为Smart-C++ 1.2.5.174)

    【Smart-C++ 1.2.5.174】是一款基于Dev-C++ 5.3.0.2深度改造的C++集成开发环境(IDE),特别针对编程竞赛进行了优化。这款IDE旨在提供一个高效、易用的平台,助力程序员在编程竞赛中快速编写、调试和优化代码。...

    visual c++ 6.0绿色版.exe

    visual c++ 6.0绿色版.exe visual c++ 6.0绿色版.exe visual c++ 6.0绿色版.exe visual c++ 6.0绿色版.exe visual c++ 6.0绿色版.exe visual c++ 6.0绿色版.exe

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

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

    C++基础入门.pdf

    C++关键字包括auto、break、case、catch、char、class、const、continue等。这些关键字不能用于定义变量或常量的名称。 1.6 标识符命名规则 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++实现...

    C++CLI实例.zip_C++/CLI_CLI封装_cli c++_naturallyu87_varietyk5o

    这个"C++CLI实例.zip"文件包含了一系列关于C++/CLI的实践案例,旨在帮助初学者理解如何使用C++/CLI进行.NET开发,以及如何进行CLI封装,使得C++代码能够被C#等其他.NET语言调用。 C++/CLI是C++的一个扩展,它引入了...

    一种用C++动态扩展C++程序的方法.pdf

    ### 一种用C++动态扩展C#程序的方法 #### 引言 随着计算机科学的发展,越来越多的项目需要结合多种编程语言的优势来构建高效且灵活的应用系统。C++作为一种功能强大且广泛应用的语言,拥有大量的现有代码库;而C#...

    Single-header C++ HTTP request class.zip

    标题 "Single-header C++ HTTP request class.zip" 指向的是一个C++库,它提供了一个简单的HTTP请求类,该类被设计为单头文件,方便集成到项目中。这样的库通常是为了简化C++开发中的网络通信,尤其是HTTP请求操作。...

Global site tag (gtag.js) - Google Analytics