设计一个类的时候,需要考虑的问题:
1、你的类需要一个构造函数吗?
可能需要一个构造函数来隐藏内部工作方式。
2、你的数据成员是私有的吗?
保证数据的实时性,有效性。比如长度,如果是共有的,被修改了,就不能正确的表达原先所谓的“长度”。
3、你的类需要一个无参构造函数吗?
没有的话,等于禁止了对象数组。
class Point
{
public:
Point(int p, int q):x(p),y(q){}
//...
private:
int x, y;
};
Point p; //error
Point pa[100]; //error
每个构造函数都要负责为所有的数据成员设置经过明确定义的值。但也未必。
5、类需要析构函数吗?
类是不是分配了资源,而又不能由成员函数自动释放。
特别是的构造函数里包含了new表达式的类,通常要在析构函数中delete掉。
6、类需要一个虚析构函数吗?
决不会作为基类的类是不需要虚析构函数的:任何虚函数只有在继承的情况下才有用。
虚析构函数通常是空的。
struct B
{
string s;
virtual ~B() {}
};
struct D : B
{
string t;
};
int main()
{
B* bp = new D;
delete bp; //除非B有一个虚析构函数,否则会调用错误的析构函数。
}
7、你的类需要复制构造函数吗?
关键在于复制该类的对象是否就相当于复制该数据成员和基类对象。
如果你的类在构造函数内分配资源,则可能需要一个显示的复制构造函数来管理资源。
有析构函数(除了空的虚析构函数外)的类通常是用析构函数来释放构造函数分配的资源。
如果不想用户能够复制类的对象,就声明复制构造函数为私有的。
8、你的类需要一个赋值操作符吗?
如果需要复制构造函数,同理多半也会需要一个复制操作符。
如果不想用户能够设置类中的对象,就将赋值操作符私有化。
类X的辅助由X::operator=来定义。通常,operator=应该返回一个X&,
并且由 “return *this;” 结束,来保证与内建的复制操作符一致。
9、你的复制操作符能正确地将对象赋给对象本身吗?
思考一下类他String:
#include <iostream>
#include <string.h>
using namespace std;
class String
{
public:
String& operator=(const String& s);
private:
char* data;
};
我们很容易就用下面的方法来实现赋值:
String& String::operator=(const String& s)
{
delete []data;
data = new char[strlen(s.data)+1];
strcpy(data, s.data);
return *this;
}
可是一旦我们把一个String对象赋值给它本身,那就会彻底失败。
因为s和*this都是指向同一个对象。
//正确的实现方法1
String& String::operator=(const String& s)
{
if (&s != this)
{
delete []data;
data = new char[strlen(s.data)+1];
strcpy(data, s.data);
}
return *this;
}
//正确的实现方法2
String& String::operator=(const String& s)
{
char* newdata = new char[strlen(s.data)+1];
strcpy(newdata, s.data);
delete []data;
data = newdata;
return *this;
}
只要用户想创建你的类型的有序集合,你就必须提供关系操作符。
11、删除数组时你记得用delete[ ]吗?
12、记得复制构造函数和赋值操作符的参数类型中加上const了吗?
类X的复制构造函数应该类似: X::X(const X&)。
赋值应该类似:X::operator=(X&)。
13、如果函数有引用参数,他们应该是const引用?
只有当函数想改变参数时,它才应该有不用const声明的引用参数。
所以,例如,不应该用
Complex operator+(Complex& x, Complex& y);
而应该用
Complex operator+(const Complex& x, const Complex& y);
除非你想允许增加两个Complex对象来改变他们的
值!
否则,由于x+y不是左值,只是一个零时对象,就不能绑定一个非const引用到本身,
只能将其办定到const对象的引用上。
所以类似于x+y+z的表达式就不可用了。
PS: 不理解这句话的同学,可以看这个链接:
http://bbs.csdn.net/topics/360011369
14、记得适当地声明成员函数为const的了吗?
如果确信一个成员函数不能修改它的对象,就可以声明它为const,
这样就把它用于const了。
#include <iostream>
using namespace std;
class Pen
{
public:
Pen()
{
length = 10;
}
int Length()
{
return length;
}
private:
int length;
};
int main()
{
const Pen p1;
cout << "length of p1 : " << p1.Length() << endl;
return 0;
}
error: passing 'const Pen' as 'this' argument of 'int Pen::Length()' discards qualifiers [-fpermissive]
//正确代码2
#include <iostream>
using namespace std;
class Pen
{
public:
Pen()
{
length = 10;
}
int Length() const
{
return length;
}
int Lenght()
{
return length;
}
private:
int length;
};
int main()
{
const Pen p1;
cout << "length of p1 : " << p1.Length() << endl;
Pen p2;
cout << "length of p2 : " << p2.Length() << endl;
return 0;
}
//length of p1 : 10
//length of p2 : 10
不理解的同学,可以参考这条链接:
http://www.cnblogs.com/this-543273659/archive/2011/07/18/2109922.html