• C++11实现模板手柄:委托构造函数、defaultkeyword分析


    C++11。使用委托构造函数。和高速变量初始化,defaultkeyword重新声明默认构造函数,回答pod状态。

    分析与推荐的方法。

    到目前为止,VS2012和2013异常声明兼容还是停留在通信代码级,查,出现例如以下错误可忽略。

    warning C4290: 忽略 C++ 异常规范,但指示函数不是 __declspec(nothrow)


    下为:VS2012不支持托付构造函数。建议使用cocos2d-x 3.2及版本号的朋友更新VS至2013版。

    1>d:cpp_lab estqueue_16th_2 estqueue_16th_2handle.hpp(9): error C2614: “Handle<T>”: 非法的成员初始化:“Handle<int>”不是基或成员

    同一时候VS2012也不支持高速初始化变量。



    VS2013同一时候完毕了对于default声明。可是假设考虑和委派构造函数一起使用的话,则会有例如以下的错误:

    Handle() = default:Handle(p,new std::size_t(1)){};

    1>d:cpp_2013	estqueue_16th_2	estqueue_16th_2handle.hpp(7): error C2143: 语法错误 : 缺少“;”(在“:”的前面)

    编译时出现语义上的二义性。要又一次定义=():()形式的语义?

    原因在:一旦使用defaultkeyword去重定义默认的构造函数使其回复至pod状态,要记得不能定义函数体,默认构造函数是由编译器合成的。

    若定义了default构造函数的函数体,则会出现重载定义无法识别的编译报错。

    VS2013版源代码例如以下:

    class Handle
    {
    public:
    <span>	Handle() = default; // 不能声明函数体</span>
    	Handle(T *p = nullptr):Handle(p,new std::size_t(1))
    	{
    	}
    
    
    	Handle(const Handle & h):Handle(h.m_pPtr,h.m_pUseCount)//托付构造函数,将先调用目标构造函数,再完毕初始化
    	{
    		
    	}
    
    	Handle & operator = (const Handle & other);
    
    
    	T & operator *() throw (std::runtime_error);
    	T * operator ->() throw (std::runtime_error);
    
    	T & operator *() const throw (std::runtime_error);
    	T * operator ->() const throw (std::runtime_error);
    
    	~Handle(void)
    	{
    		rem_ref();
    	}
    
    private:
    	Handle(T*p,size_t * use):m_pPtr(p),m_pUseCount(use) // 目标构造函数
    	{
    		if (m_pPtr==nullptr)
    		{
    			 delete m_pUseCount;
    			 m_pUseCount = nullptr;
    		}
    <span style="font-family: Arial, Helvetica, sans-serif;"><span>				</span>else</span>
    <span style="font-family: Arial, Helvetica, sans-serif;"><span>				</span>{</span>
    <span style="font-family: Arial, Helvetica, sans-serif;">					</span><span style="font-family: Arial, Helvetica, sans-serif;">++(*m_pUseCount);</span>
    </pre><pre name="code" class="cpp"><span style="font-family: Arial, Helvetica, sans-serif;"><span>				</span>}</span>
    	};
    
    	void rem_ref()
    	{
    		if (--*m_pUseCount == 0)
    		{
    			delete m_pPtr;
    			delete m_pUseCount;
    			m_pPtr = nullptr;
    			m_pUseCount = nullptr;
    		}
    	}
    
    private:
    	T * m_pPtr = nullptr;//实际上这个赋值没太多意思
    <span>	</span>size_t * m_pUseCount = nullptr;
    
    };
    
    
    template <typename T>
    Handle<T> & Handle<T>::operator = (const Handle<T> & other)
    {
    	++other.m_pUseCount;
    	rem_ref();
    	m_pPtr = other.m_pPtr;
    	m_pUseCount = other.m_pUseCount;
    	return *this;
    }
    
    
    template <typename T>
    inline T & Handle<T>::operator *()
    {
    	if (m_pPtr!=nullptr)
    	{
    		return *m_pPtr;
    	}
    	else
    	{
    		throw std::runtime_error("dereference of unbound Handle");
    	}
    	
    }
    
    template <typename T>
    inline T * Handle<T>::operator ->()
    {
    	if (m_pPtr!=nullptr)
    	{
    		return m_pPtr;
    	}
    	else
    	{
    		throw std::runtime_error("dereference of unbound Handle");
    	}
    }
    	
    template <typename T>
    inline T & Handle<T>::operator *() const
    {
    	if (m_pPtr!=nullptr)
    	{
    		return *m_pPtr;
    	}
    	else
    	{
    		throw std::runtime_error("dereference of unbound Handle");
    	}
    }
    
    template <typename T>
    inline T * Handle<T>::operator ->() const
    {
    	if (m_pPtr!=nullptr)
    	{
    		return m_pPtr;
    	}
    	else
    	{
    		throw std::runtime_error("dereference of unbound Handle");
    	}
    }

    main函数:

    int*p = new int(100);
    
    	Handle<int> pInt(p);
    
    	Handle<int> pInt2 = Handle<int>(pInt);
    
    	Handle<int> pInt3 = pInt2;
    
    	try
    	{
    		cout << *pInt << "	" << *pInt2 << "	" << *pInt3 << endl;
    	}
    	catch (runtime_error e)
    	{
    		cerr<<e.what()<<endl;
    	}
    
    	try
    	{
    		*pInt3 = 200;
    		cout << *pInt << "	" << *pInt2 << "	" << *pInt3 << endl;
    	}
    	catch (runtime_error e)
    	{
    		cerr << e.what() << endl;
    	}
    
    	int i = 0;
    	try
    	{
    		pInt.~Handle();
    		cout << ++i << "	" << *pInt << "	" << *pInt2 << "	" << *pInt3 << endl;
    		
    		pInt.~Handle();
    		cout << ++i << "	" << *pInt << "	" << *pInt2 << "	" << *pInt3 << endl;
    	}
    	catch (runtime_error e)
    	{
    		cerr << e.what() << endl;
    	}
    
    	try
    	{
    		
    
    		pInt.~Handle();
    		cout << ++i<< "	" << *pInt << "	" << *pInt2 << "	" << *pInt3 << ends; /*运行了前面的++操作,可是出现异常。异常销毁仅仅会析构和处理变量。不会回滚操作*/
    	}
    	catch (runtime_error e)
    	{
    		cerr << i << "	"<< e.what() << endl;
    	}
    

    委派构造函数的使用在于内部能定义一个完整版本号的构造函数,然后在类对象未完毕初始化时调用该构造函数,先在当前地址完毕构造。这个思维应该是曾经this为很量时代(事实上我没用过很量指针形式的this)的使用方法,后来新标准定义this仅仅能为const类型,融合当前代码时长出现大量的构造函数。思考出的解决方式,不算是语法上的突破或革新。

    程序结果:

    源代码

    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    UIrecorder脚本录制与回放
    通过jmeter读取csv的case来实现接口自动化
    Jmeter操作MySQL数据库详解
    使用docker安装Jenkins
    CMMS / EAM与工厂其它业务流程的交集,融合趋势有哪些
    如何让CMMS系统适应您的企业
    CMMS系统中的物联监测
    CMMS系统中工单派案&调度
    移动化的设备维护管理系统--移动端界面
    物流行业设备维护管理系统
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4822828.html
Copyright © 2020-2023  润新知