more effective c++——Item M30 代理类(三)隐式类型转换与代理类

代理类的缺点:
1.作为函数返回值,代理类的临时对象(比如proxychar)会带来构造与析构的开销
2.代理类存在类型转换的问题,如果原始类A可以隐式转换为类B,则代理类即使存在隐式转换为A的方法,也不能直接转换为B
3.如果要像操作原始类一样操作代理类,则必须为代理类提供相同的接口

根据第二点的特性,我们可以设计一个转换的代理类来防止隐式类型(另一种方式是将单参构造函数声明为explicit)。比如有一个类CArrayInt,开始设计如下:

class CArrayInt
{
public:
    CArrayInt(int size) :m_size(size), m_data(new int[m_size]) {}
    int &operator[](CArrayInt &rhl){...}
    CArrayInt &operator=(const CArrayInt &rhl){...}
    bool operator==( const CArrayInt &lhs,const CArrayInt &rhs);
    ~CArrayInt() { delete[] m_data; }
private:
    int m_size;
    int *m_data;
};

使用:

CArrayInt ci1(5);// 构造一个CArrayInt 对象
CArrayInt ci2(5);
// do something
if(ci1 == ci2[2]){
    //do otherthing
}

上面的操作肯定是存在问题的,我们原本希望对ci[2]进行赋值,如果我们写出了上面的代码,希望编译器会报错,但是不然。因为ci2[2]返回的是一个int,可以通过CArrayInt 的单参构造函数转换为一个临时的CArrayInt 对象,因此ci1 == ci2[2]实际上等价于ci1 == CArrayInt(ci2[2])。如何避免这个问题?答案就是通过代理类ArraySize实现,加入代理类后的代码如下:

class CArrayInt
{
public:
    class ArraySize {
    public:
        ArraySize(int size) :m_size(size) {}
        int m_size;
    };
    CArrayInt(ArraySize &size) :m_size(size.m_size), m_data(new int[m_size]) {}
    ~CArrayInt() { delete[] m_data; }
private:

    int m_size;
    int *m_data;
};
void test_proxy_constructor()
{
    CArrayInt ci1(CArrayInt::ArraySize(5));// ok
    ci1 = 8;// error,int类型不可以直接转换为CArrayInt,只有ArraySize才可以
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值