- C中的字符常量其实是未命名的字符数组(由编译器在尾部插入空字符'/0'来标识串尾)
char hello[] = "hello"; valid
char hello[5];
hello = "hello"; invalid
初始化时,数组的长度必须大于等于字符常量的长度+1
char hello[5] = "hello"; invalid
char hello[6] = "hello"; valid
- 墨非法则(Murphi's law)
起源于20世纪初美国的一个叫墨非的倒霉蛋,大意是说一件事情只要有可能变糟,就一定会变糟。比如从餐桌上掉下的面包片总是涂了果酱的一面掉地,电影院里迟到的人总是坐在前排。
- 类需要一个构造函数么
有些类很简单,它们的结构就是它们的接口,所以不需要构造函数。
- 你的数据成员是私有的么
通常使用共有的数据成员不是什么好事,因为类设计者无法控制何时访问这些成员。
- 类需要析构函数么
不是所有有构造函数的类都需要析构函数,例如:表示复数的类即使有构造函数也可能不需要析构函数。
- 类需要一个虚析构函数么
有写类需要虚析构函数只是为了声明它们的析构函数是虚的,当然,决不会用作基类的类是不需要虚析构函数的。任何虚函数只在继承的情况下才有用。但是,你写了一个叫B的类,而别人从它派生了一个类D,那么B何时需要一个虚析构函数?只要有人可能会对实际指向D类型对象的B*指针执行delete表达式,你就需要给B加上一个虚析构函数。即使B和D都没有虚函数,这也是需要的。
struct B{
String S;
};
struct D: B{
String t;
};
int main()
{
B * bp = new D;
delete bp;
}
这里,即使B没有虚函数,实际上连成员函数也没有,如果B有一个虚析构函数,那么Delete会出错,虚析构函数通常是空的。
- 你的类需要一个无参的构造函数么
如果一个类已经有了一个构造函数,而你想声明该类的对象可以不必显示的初始化它们,则必须显示的写一个无参的构造函数。
- 是不是构造函数初始化所有成员
构造函数的用途就是用一种明确定义的状态来设置对象。对象的状态由对象的数据成员进行反映。因此每个构造函数都要负责为所有的数据成员设置经过明确定义的值。这种说法不总是正确,但却可以激励进行思考。
- 类需要复制构造函数么
很多时候答案都是"不",但有时候答案是"是"。关键在于复制构造该类的对象是否相当于复制其数据成员和基类对象。如果并不项当,就需要复制构造函数。
如果你的类在构造函数内分配资源,则可能需要一个显示的复制构造函数来管理资源。
如果不想用户能够复制类的对象,就声明复制构造函数(可能还有赋值操作符)为私有的
- 类需要一个赋值操作符么
如果需要复制构造函数,同理多半也需要一个赋值操作符
- 赋值操作符能正确将对象付给对象本身么
赋值总是用新值取代目标对象的旧值,如果目标对象和源对象是同一对象。就可能在没有实施赋值之前已经把原对象销毁了,例如:
class String{
public:
String& operator*(const String &s);
private:
char *data;
}
不正确的实现:
String & String::opetator=(const String&s)
{
delete [] data;
data = new char[strlen(s.data) + 1];
strcpy(data, s.data);
return * this
}
正确的实现
String & String::opetator=(const String&s)
{
if(&s != this)
{
delete [] data;
data = new char[strlen(s.data) + 1];
strcpy(data, s.data);
}
return * this
}
另一种可行的方法:
String & String::opetator=(const String&s)
{
char *newdata = new char[strlen(s.data) + 1];
strcpy(newdata , s.data);
delete [] data;
data = newdata;
return * this
}
- 类需要定义关系操作符么
如果用户想要创建你的类的有序集合,就必须提供关系操作符。
- 在赋值构造函数和赋值操作符的参数类型前加const了么
绑定一个非const引用到一个临时对象是非法的?
- 记得适当的声明成员函数为const了么
取回长度而不改变该值的函数应声明为const;
template <class T> class Vector{
public:
int length() const;
}
否则我们会遇到下面的问题:
template<class T> int padded_length(const Vector<T>&v, int n)
{
int k = v.length(); //oops 该编译通不过
return k>n ? k:n;
}