2009-10-16 150 views
1

我试图使用PIMPL方法隐藏一些蹩脚的模板代码,但我不能给身体类朋友访问手柄类派生类。我从MSVC 9 sp1中收到错误C2248。下面是一些代码复制的错误:PIMPL方法和模板类的朋友

// 
// interface.hpp 
// 
namespace internal{ 
    template<class T> 
    class specific_body; 
} 

class interface 
{ 
    struct body; 
    body *pbody_; 
    interface(body *pbody); 

    template<class T> 
    friend class internal::specific_body; 

public: 

    ~interface(); 

    interface(const interface &rhs); 

    bool test() const; 

    static interface create(bool value); 
}; 

// 
// interface.cpp 
// 
struct interface::body 
{ 
    virtual ~body(){} 

    virtual bool test() const = 0; 

    virtual interface::body *clone() const = 0; 
}; 

class true_struct {}; 
class false_struct {}; 

namespace internal { 

template< class T> 
class specific_body : public interface::body 
{ // C2248 
public: 

    specific_body(){} 

    virtual bool test() const; 

    virtual interface::body *clone() const 
    { 
     return new specific_body(); 
    } 
}; 

bool specific_body<true_struct>::test() const 
{ 
    return true; 
} 

bool specific_body<false_struct>::test() const 
{ 
    return false; 
} 

} //namespace internal 

interface::interface(body *pbody) : pbody_(pbody) {} 

interface::interface(const interface &rhs) : pbody_(rhs.pbody_->clone()) {} 

interface::~interface() { delete pbody_; } 

bool interface::test() const 
{ 
    return pbody_->test(); 
} 

interface interface::create(bool value) 
{ 
    if (value) 
    { 
     return interface(new internal::specific_body<true_struct>()); 
    } 
    else 
    { 
     return interface(new internal::specific_body<false_struct>()); 
    } 
} 

// 
// main.cpp 
// 
// #include "interface.hpp" 
// 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    interface object(interface::create(true)); 

    if (object.test()) 
    { 
     // blah 
    } 
    else 
    { 
    } 
    return 0; 
} 

任何帮助,将不胜感激,我试图隐藏的interface用户interface::bodyspecific_body实现,如果这不是从我的问题很明显。

回答

0

那么的显式实例添加模板<>,我能够通过使body公开声明在界面中的“解决”这个问题。这在申报specific_body时解决了C2248错误。我也做了body的朋友可以到interface类,并增加了一个方法,将body结构:

static interface create(body *pbody) 
{ 
    return interface(pbody); 
} 

,因此如果有一种specific_body

0

你还没有资格specific_body。尝试

template<class T> 
friend class internal::specific_body; 

作为您的朋友声明。

+0

感谢实例之间的嵌套关系的specific_body可以创建一个interface建议,它不利于虽然 – Queueless 2009-10-16 18:26:58

+0

出于兴趣,所有这一切开始工作,如果你删除的命名空间'internal'即只是把'specific_body'在全局命名空间? – Troubadour 2009-10-16 23:00:17

0

尝试使用类型名称可能?我认为我在Sutter中读到typename将工作到一个未知范围内的类,而类不会。

+0

我在哪里可以使用typename? – Queueless 2009-10-16 18:30:44

+0

我想你把它放在后或朋友 – messenger 2009-10-16 18:38:04

0

除了由游吟诗人提到的不合格specific_body,specific_body <> ::试验的true_struct和false_struct您专业化的尝试似乎不正确。你必须专门的全班。

要解决该问题,我只需在公开区域声明正文。另外声明specific_body是interface :: body的朋友也没有帮助。

+0

之前,我不知道为什么缩绒专业的'specific_body'类会在这种情况下,无所谓。 我在我的代码申报身体公众一个情况下帮助,但我已经在'specfic_body'需要访问的'interface'太私有构造另一种情况;所以我想解决朋友访问问题,或者重新构造代码,以达到我可以从身体类固有的同一目标。 – Queueless 2009-10-16 18:45:03

+0

完全专业化无法使其符合C++标准。如果你没有得到那部分的任何错误,你的编译器可能会支持它作为扩展,我不知道。但GCC拒绝它。只是说... – sellibitze 2009-10-16 18:55:37

+0

你在这里看到的不符合要求是什么?只专注于模板类的成员functon而不专门研究整个类在C++中是完全合法的。非正式地讲,类模板的每个成员函数本身都是一个独立的模板,可以独立地进行专门化。这是一个很少使用的功能,但它在那里。 14.7.3/16包含了这种专业化的例子。 – AnT 2009-10-18 08:43:02

1

您需要在模板测试方法

template<> // add this line 
bool specific_body<true_struct>::test() const 
{ 
    return true; 
} 
+0

是的,我忘了在我的例子中将这些行添加到测试方法的专业化中,但他们没有帮助。感谢您的输入。 – Queueless 2009-10-19 11:24:57

+0

检查你的例子中是否没有遗漏某些东西。修复它使用gcc 4.4.1编译的行,并且正常工作。 – 2009-10-19 14:27:56

+0

好吧,他们似乎没有与微软的编译器有所作为,所以它看起来像是一个编译器一致性问题。感谢您的意见。 – Queueless 2009-10-23 17:12:09