我自己的智能指针模板编译错误

时间:2011-02-10 13:36:32

标签: c++ smart-pointers

我正在从斯科特迈耶斯的书中学习以下简单的程序。我正在使用Visual Studio 2009进行编译。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


class Top {  };

class Middle: public Top {  };

class Bottom: public Middle {  };



template<typename T>

class SmartPtr {

public:

    template<typename U>

    SmartPtr(const SmartPtr<U>& other) : heldPtr(other.get()) { }

    T* get() const { return heldPtr; }


private:

    // built-in pointer held

    T *heldPtr;

};



int main()
{
    SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle); //  SmartPtr<Top>
}

在编译期间,我收到以下错误

1>d:\technical\c++study\addressconv.cpp(36) : error C2440: '<function-style-cast>' : cannot convert from 'Middle *' to 'SmartPtr<T>'
1>        with
1>        [
1>            T=Middle
1>        ]
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
1>d:\technical\c++study\readparsing\readparsing\addressconv.cpp(36) : error C2512: 'SmartPtr<T>' : no appropriate default constructor available
1>        with
1>        [
1>            T=Top
1>        ]

请求帮助解决问题。问题的根本原因是什么?

谢谢!

5 个答案:

答案 0 :(得分:1)

您需要实现一个接受U*的构造函数。它抱怨它无法明确地将U*转换为SmartPtr<U>

答案 1 :(得分:0)

SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle()); //  SmartPtr<Top>
                                               ^^

答案 2 :(得分:0)

首先,创建两个复制构造函数。一个接受相同类型,另一个接受任何其他可以动态转换为基类型的类型。这就是我的意思。

template<typename T>
class SmartPointer
{
    // No dynamic_cast and hence no overhead
    SmartPointer(const SmartPointer<T>& other):heldPtr(other.heldPtr){}

    // Has dynamic_cast'ing
    template<typename U>
    SmartPointer(const SmartPointer<U>& other):heldPtr(dynamic_cast<T*>(other.get())){}

    // Rest of the code
}

请记住,根据您的代码,基类指针不会与派生类SmartPtr保持相同的引用计数。这意味着如果基类或派生类SmartPtr超出范围,指针将变为无效。

编辑:这绝对有效。基本问题是没有一个构造函数将指针作为参数来创建SmartPtr。这是工作代码。

class Top
{
public:
    virtual ~Top(){}
};

class Middle: public Top
{
public:
    virtual ~Middle(){}
};

class Bottom: public Middle
{
};


template < typename T >
class SmartPtr
{
public:

    explicit SmartPtr(T* ptr):heldPtr(ptr){}

    SmartPtr(const SmartPtr<T>& other) : heldPtr(other.heldPtr){}

    template<typename U>
    SmartPtr(const SmartPtr<U>& other) : heldPtr(dynamic_cast<T*>(other.get())) { }

    T* get() const { return heldPtr; }

private:

    // built-in pointer held

    T *heldPtr;

};

我希望这会有所帮助。我还使基类的析构函数动态化,因为这是任何要继承的类所必需的。

答案 3 :(得分:0)

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;



class Top {  };

class Middle: public Top {  };

class Bottom: public Middle {  };



template<typename T>
class SmartPtr {
public:

    SmartPtr(T* other):heldPtr(other){}

    SmartPtr(const SmartPtr<T>& other):heldPtr(other.heldPtr){} 

    template<typename U>
    SmartPtr(const SmartPtr<U>& other) // initialize this held ptr
        : heldPtr(other.get()) { } // with other’s held ptr

    T* get() const { return heldPtr; }

private: 
    // built-in pointer held
    T *heldPtr; // by the SmartPtr
};


int main()
{
    SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle()); //  SmartPtr<Top>
}

答案 4 :(得分:0)

您遇到的错误很简单:没有SmartPtr的构造函数将简单T*(或U*)作为参数。添加以下内容:

template <typename U>
SmartPtr(U* ptr): heldPtr(ptr) {}

并且您的代码应该编译。

关于复制构造函数:确保传输所有权或实现引用计数,否则您将遇到麻烦。