我怀疑我不能使用PIMPL模式直接执行此操作。是否可以有一个指向模板类的智能指针?我无法通过转动shared_ptr
声明上的旋钮进行编译。
// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<T> > m_impl;
};
// ============FooImpl.h ============
template <typename T>
class FooImpl
{
...
};
在Visual Studio 2008下:“错误C2065:'T':未声明的标识符”。我在GCC下收到类似的错误。 如果我取消参数化FooImpl(以便FooTempl继承自FooImpl),代码将被编译。
我怀疑我不能对智能指针进行参数化,但我可能错了。
编辑:第二个 Visual Studio错误更有说服力:“错误C3203:'FooImpl':非专用类模板不能用作模板参数'T'的模板参数,预期a真实的类型“
杰夫
答案 0 :(得分:3)
我不完全确定你想要完成什么,但这有帮助吗?
// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;
template<class C>
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<C> > m_impl;
};
// ============FooImpl.h ============
template <typename T>
class FooImpl
{
...
};
// ============Foo.h ============
// Forward declare the implementation
class FooImplBase;
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImplBase > m_impl;
};
// ============FooImpl.h ============
class FooImplBase {
public:
virtual void AnAPI();
virtual int AnotherAPI();
};
template <typename T>
class FooImpl : public FooImplBase
{
...
};
答案 1 :(得分:1)
您做得对,只需确保T
已定义。这在MSVC ++ 2010上为我编译:
#include <memory>
using namespace std;
template<class T>
class Blah {
public:
Blah() { }
};
class Foo {
public:
shared_ptr<Blah<int>> ptr;
Foo() : ptr(new Blah<int>()) { }
};
如果您使用的旧编译器尚未包含C ++ 11的此功能,请更改
shared_ptr<Blah<int>> ptr;
到
shared_ptr<Blah<int> > ptr;
因此编译器认为>>
不是正确的转变。但是C ++ 11没有这个问题。
答案 2 :(得分:1)
我事先并不知道我会有一个Blah,只有一个Blah。
从语言的角度来看,Blah<T>
毫无意义,因为T
不存在。根据您正在尝试做的事情,您可以
使Foo
成为模板,以便您可以声明模板参数T
:
template<typename T>
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<T> > m_impl;
};
在声明T
类型的变量时“修复”Foo<T>
的选择;
或使FooImpl
显式派生于一个共同基础:
class FooBase {
// need to define the interface here
};
// this is a class definition whereas previously you only needed a declaration
template<typename T>
class FooImpl: public FooBase {
// definition here
};
class Foo
{
public:
Foo getInstance(const string& fooType);
// we needed the definition of FooImpl for this member
// in addition this member is quite obviously a template
template<typename T>
void
set(FooImpl<T> const& foo)
{
m_impl.reset(new FooImpl<T>(foo));
}
// not a member template!
void
use()
{
// any use of m_impl will be through the FooBase interface
}
private:
shared_ptr<FooBase> m_impl;
};
对于给定的Foo
实例,可以动态设置任何类型的FooImpl<T>
,然后通过FooBase
接口使用。{{1}}这是在C ++世界中调用的type erasure。
答案 3 :(得分:1)
您发布的代码无法编译,因为T
在Foo
的上下文中没有任何意义。编译器需要一个名为T的类型,在那里不存在...不完全确定你想要完成什么,但是下面的解决方案不会解决你的问题吗?
// ============Foo.h ============
class FooImplBase {
virtual void WhateverFooImplIsSupposedToDo() = 0;
};
template <typename T> class FooImpl : public FooImplBase {
T mInstance;
public:
FooImpl(T const & pInstance) : mInstance(pInstance) {}
virtual void WhateverFooImplIsSupposedToDo()
{
// implementation which deals with instances of T
}
};
class Foo
{
public:
Foo getInstance(const string& fooType) {
// use m_impl->WhateverFooImplIsSupposedToDo...
}
template < class T >
Foo( T const & pInstance ) : m_impl(new FooImpl<T>(pInstance)) {}
private:
shared_ptr< FooImplBase > m_impl;
};
答案 4 :(得分:0)
我们可以使用模板编写通用的智能指针类。以下C ++代码演示相同。我们不需要调用delete'ptr',当对象'ptr'超出范围时,它的析构函数会自动生成。
#include<iostream>
using namespace std;
// A generic smart pointer class
template <class T>
class SmartPtr
{
T *ptr; // Actual pointer
public:
// Constructor
explicit SmartPtr(T *p = NULL) { ptr = p; }
// Destructor
~SmartPtr() {
cout <<"Destructor called" << endl;
delete(ptr);
}
// Overloading dereferncing operator
T & operator * () { return *ptr; }
// Overloding arrow operator so that members of T can be accessed
// like a pointer (useful if T represents a class or struct or
// union type)
T * operator -> () { return ptr; }
};
int main()
{
SmartPtr<int> ptr(new int()); // Here we can create any data type pointer just like 'int'
*ptr = 20;
cout << *ptr;
return 0;
}
out put:
20
析构函数叫