我正在从斯科特迈耶斯的书中学习以下简单的程序。我正在使用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> ]
请求帮助解决问题。问题的根本原因是什么?
谢谢!
答案 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) {}
并且您的代码应该编译。
关于复制构造函数:确保传输所有权或实现引用计数,否则您将遇到麻烦。