Linux C/C++ 模板:模板安全

一、非模板安全的代码

#include <iostream>
using namespace std;

template <typename T>
class wrapper
{
public:
        wrapper() { }

        T get() { return m_value; } //part 2
        void set(T const &value) { m_value = value; } //part 3

private:
        T m_value; //part 1

        wrapper(wrapper const &);
        wrapper& operator=(wrapper const &);
};

int main(int argc, char* argv[])
{

        return 0;
}

二、模板安全分析与解决

2.1 模板安全分析

        如果T为int,即wrapper<int>,没有任何问题。

        如果T是一个类,会有3个潜在的模板安全问题:

                1. T m_value   会调用类T的构造函数,可能会抛出异常;

                2. T get() { return m_value; }   会调用类T的构造函数,构造T的一个临时对象,可能会抛出异常;

                3. void set(T const& value) { m_value = value; }   会调用类T的赋值运算符,可能会抛出异常。

2.2 T m_value 解决办法

        1. 构造函数中,不能抛出function-try异常。

        2. 将隐式构造改成显式构造,即:

        wrapper() : m_value(NULL)
        {
                m_value = new T; 
        }

        3. m_value = new T可能会抛出异常:

        wrapper() : m_value(NULL)
        {
                try { m_value = new T; }
                catch (...) {   }
        }
        4.  需要增加析构时释放函数:

                调用delete m_value析构时如果抛出异常,需要手动delete m_value(catch(...) { })

                如果catch(...) { }中的delete m_value再抛出异常,程序将2次处于异常状态,会调用terminate()。

        ~wrapper() throw()
        {
                try { delete m_value; }
                catch (...) { operator delete(m_value); }
        }

 

2.3 T get() { return m_value; } 解决办法

        1. 将隐式构造改为显式:

        void get(T& value) 
        { 
                value = m_value;
        }

        2. value = m_value赋值运算符, 可能会抛出异常:

        void get(T& value)
        {
                try { value = m_value; }
                catch(...) { }
        }
        3. 即便处理的异常,返回的value处于不确定状态,调用者不知道其是什么状态:

                用返回值,来标示value,是赋值完成,还是没有完成。

        bool get(T& value)
        {
                bool error = false;

                try { value = m_value; }
                catch(...) { error = true;  }

                return error;
        }

2.4 void set(T const& value) { m_value = value; } 解决办法

        参照2.3节的,第2、3步。

三、模板安全的代码

#include <iostream>
using namespace std;

template <typename T>
class wrapper
{
public:
        wrapper() throw() : m_value(NULL)
        {
                try { m_value = new T; }
                catch (...) {   }
        }

        ~wrapper() throw()
        {
                try { delete m_value; }
                catch (...) { operator delete(m_value); }
        }

        bool get(T& value) const throw() { return assgin(value, *m_value); }
        bool set(const T& value) throw() { return assgin(*m_value, value); }

        void output() { cout<<m_value<<endl; }

private:
        T* m_value;

        bool assign(T& to, T const & from) throw()
        {
                bool error(false);

                try { to = from; }
                catch (...) { error = true; }

                return error;
        }

        wrapper(wrapper const &);
        wrapper& operator=(wrapper const &);
};

int main(int argc, char* argv[])
{

        return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值