notes of Effective C++

在Effective C++ I 上看到的代码:
class A{
public:
    A(int aa): a(aa) {}
private:
    int a;
};

class B{
public:
    explicit B(int bb = 0): b(bb) {}
private:
    int b;
};

void funa(A a)
{
    cout << "right" << endl;
}

void funb(B b)
{
    cout << "right" << endl;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    B objB1;
    funb(objB1);
    funa(28);
    return 0;
}

可以编译通过的,然后

funb(28)
无法通过编译,原因是B的定义中使用了explicit关键字,阻止了构造函数被用来执行隐式类型转换。funa会自动调用A的构造函数构造A类型的对象。下面两种方式都可以通过编译:

funb(B(28))
funb(static_cast<B>(15))
第一种方式是调用B的构造函数进行了显式转换,第二种方式使用了static_cast,也创建了B对象。(Effective C++ I条款27)

在条款27中提到的Tips:

(1)const_cast:执行常量型转移的动作,也只有该动作可以将const转为non-const;

(2)如果Base和Derive类都实现了virtual function(例如onResize),那么如果在Derive类中如果要调用Base中的onResize,调用方式是Base::onResize(); 而非static_cast<Base>(*this).onResize(),原因是这种方式会导致先创建*this指针的副本,转换为Base类,然后更改了副本的某些成员,但*this指针所指并没有改变。


在条款34中提到的Tips:

(1)A是base类,B、C分别public继承自A,A中定义了纯虚函数fly(),在B、C中必须实现fly;但在A中也可以有A的纯虚函数实现,实现后可以在B、C中以A::fly()的形态调用。


导读中的Tips:

class Widget{
public:
    Widget();                               //default构造函数
    Widget(const Widget& rhs);              //copy构造函数
    Widget& operator=(const Widget& rhs);   //copy assignment操作符
};

Widget w1;                                  //调用default构造函数
Widget w2(w1);                              //调用copy构造函数
w1 = w2;                                    //调用copy assignment
Widget w3 = w2;                             //调用copy构造函数
判断的关键是:是否有新的对象被定义。有的话就有构造函数被调用。


条款3中的Tips:

(1)将const实施于成员函数的目的,是为了确认该成员函数可作用于const对象身上。

(2)两个成员函数如果只是常量性不同,可以被重载。

(3)如果函数的返回类型是个内置类型,那么改动函数返回值从来就不合法。


条款4中的Tips:

(1)singleton模式

作用是保证一个类只有一个实例,并提供全局唯一的访问点。一个实例:

#ifndef _SINGLETON_H_
#define _SINGLETON_H_

class Singleton
{
private:
    static Singleton* pInstance;//静态成员,保存对象的唯一实例
    Singleton();//私有化构造函数,使其无法在类外实例化
public:
    static Singleton* Instance();
    //void Destroy();
    static void Destroy();
};

#endif

#include "Singleton.h"
#include <iostream>

using namespace std;

Singleton* Singleton::pInstance = NULL;

Singleton::Singleton()
{
    cout<< "Singleton..." << endl;
}

Singleton* Singleton::Instance()
{
    if(NULL == pInstance)
    {
        pInstance = new Singleton();
    }
    return pInstance;
}

void Singleton::Destroy()
{
    delete pInstance;
    pInstance = NULL;
    cout<< "Destroy..." << endl;
}

条款5中的Tips:

(1)如果你声明了一个构造函数,编译器不再为该类创建默认无实参构造函数。


条款6中的Tips:

(1)实现一个对象不可被复制的类:如果你不显式定义copy构造函数和copy assignment函数,编译器会自动为你实现这两个函数,所以我们的做法是定义private的copy构造函数和copy assignment 函数。


条款7中的Tips:

(1)如果基类Base的析构函数没有被定义为virtual,在用基类指针销毁一个Derive对象时,会发生derived成分没被销毁的情况。解决方案是将基类的析构函数定义为virtual。

(2)任何带有virtual函数的类机会都需要一个virtual析构函数。

(3)如下代码:

#include <iostream>
using namespace std;

class Base{
public:
    virtual ~Base() {cout<< "base!" << endl;}
};

class Derive:public Base{
public:
    ~Derive() { cout << "derive!" << endl;}
};

int main(int argc, const char * argv[]) {
    // insert code here...
    Base* d = new Derive();
    delete d;
    return 0;
}

输出为

derive!

base!

说明当Derive对象析构时调用顺序还是derive然后base,即使当Base的析构函数被定义为virtual。

条款11中的Tips:

(1)防止自我赋值问题的有效做法是证同测试。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值