my own smart pointer template compilation error
I am having following simple program from scott meyers book. I am compiling using 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<开发者_Python百科;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>
}
During compilation i am getting following error
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> ]
Kindly request to help in resolving problem. What is root cause of problem?
Thanks!
You need to implement a constructor that accepts a U*
. It's complaining that it cannot explicitly convert a U*
to a SmartPtr<U>
.
First of all, create two copy constructors. One to accept the same type and the other to accept any other type that can be dynamically casted to the base type. Here's what I mean.
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
}
Do keep in mind that according to your code, the base class pointer is not keeping the same reference count as the derived class SmartPtr. Which mean if either the base-class or derived-class SmartPtr goes out of scope, the pointer will become invalid.
EDIT: This definitely works. The basic issue was there wasn't a constructor that took a pointer as argument to create a SmartPtr. Here's the working code.
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;
};
I hope this helps. I also made the destructors of the base classes dynamic because that's required of any classes that are intended to be inherited.
SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle()); // SmartPtr<Top>
^^
#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>
}
The error you have is simple: there is no constructor of SmartPtr
taking a simple T*
(or U*
) as a parameter. Add the following:
template <typename U>
SmartPtr(U* ptr): heldPtr(ptr) {}
and your code should compile.
With regard to the copying constructors: make sure you either transmit ownership or implement reference counting, otherwise you'll be in trouble.
精彩评论