改善程序的55个具体做法

1、确定对象在使用之前被初始化

(1)为内置对象进行手工初始化(因为C++不保证初始化它们)
(2)构造函数最好使用成员初始化列表,而不要在构造函数本体内使用赋值操作。

2、一个空类会默认生成哪些函数?

defult构造函数、copy构造函数、(非虚的)析构函数、赋值运算操作符函数operator=
【注】什么情况下,赋值运算操作符函数operator=不会自动生成,或者生成的不能被编译成功?
①如果生成的代码不合法或者生成的代码无意义时
②如果父类将赋值运算操作符函数operator=声明为“private”,则编译器拒绝为子类生成赋值运算操作符函数operator=(因为编译器为子类生成的赋值运算操作符函数operator=原本想可以处理父类成分)。

【operator=运算符重载的格式】
    A& A::operator=(const A& rhs)  //返回值类型是 --> 类的引用A& 
    {
        return *this//返回的是 --> this指针指向的对象*this
    }

【处理自我赋值=的情况】在程序中,难免会遇到“隐式的自我赋值”的情况,会带来不可预知的错误,因此处理“自我赋值”成为了必不可少的一步!(用下面的例子进行说明如何处理自我赋值)
class Widget {  
public:  
  Widget(int x=0): val(new int(x)) {}  
  ~Widget() { delete val; }  
  Widget(const Widget &rhs): val(new int(*rhs.val)) {}  

  Widget& operator=(const Widget &rhs);   //operator =  

  void print() const { cout << *val << endl; }  
private:  
  int *val;  
};  
Widget& Widget::operator=(const Widget &rhs) {  //错误版本
  delete val;  
  val = new int(*rhs.val);  
  return *this;  
}  
Widget& Widget::operator=(const Widget &rhs) { 
//改进版本1:虽然具有自我复制安全性,但是不具有异常安全性。 
//如果 new int 抛出异常的时候,this->val 指向的就是一个已经删除的int
  if(this == &rhs) return;  

  delete val;  
  val = new int(*rhs.val);  
  return *this;  
}  
Widget& Widget::operator=(const Widget &rhs) {  
//改进版本2:异常安全性与自我复制安全性兼具
  int *pOld = val;  //记住原先的val
  val = new int(*rhs.val);  //令val指向*val的一个附件(副本)
      delete pOld;  //删除原先的val
  return *this;  
}  
Widget& Widget::operator=(const Widget &rhs) {  
//改进版本3:copy and swap 技术
  Widget temp(rhs);  
  swap(temp);  
  return *this;  
}  
Widget& Widget::operator=(Widget rhs) { 
//改进版本4:通过传值来实现 copy and swap  
  swap(rhs);  
  return *this;  
}  

【技巧】若不想使用编译器自动生成的函数(copy构造、赋值运算符operator=),应该怎么做?
    -->将相应的成员函数显示的声明为private类型。

3、虚析构函数

(带有多态性质的)父类析构函数应该声明为virtual析构函数,防止“局部销毁”造成的内存泄漏。

不作为父类的虚函数不要声明为virtual(因为会占用更多的空间)

4、

在构造函数和析构函数中,不要调用virtual,因为这种调用从来不会实现多态(为什么不会实现多态?——>分析父类子类对象构造、析构的顺序和多态实现的原理)

5、传递参数时,尽量以pass-by-reference-const替换pass-by-value。前者通常比较高效,并可以避免切割问题(注:该规则并不适用于内置类型、STL的迭代器和函数对象,对它们而言,pass-by-value往往比较合适)

例:
bool validataStudent(const Student& s);
void printNameAndDisplay(const Window& w);

6、必须返回对象时,别忘想返回其reference

例如重载的*运算符:
const A operator*(const A& A1,const A& A2)
{
    return A(A1.value * A2.value);
}

7、protected并不比public更具有封装性
8、尽量用non-member、non-frend函数替换member函数。
9、尽量少做转型动作

(T)expression;或者T(expression); //两种C中的转型格式
//C++提供四种新式转型
const_cast<T>(expression)//通常将对象的const性移除(它是唯一有此能力的C++-style转型操作符)
dynamic_cast<T>(expression)//主要用于“安全向下转型”,是唯一无法由旧式语法执行的动作
reinterpret_cast<T>(expression)//例如:指针转为int
static_cast<T>(expression)//例如:non-const转为const,int转为double等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值