2008-12-30 116 views
3

我使用PIMPL方法并想参照的向前声明的类的方法之一。下面不是我正在做的,而是使用相同的概念。正向申报方法指针

template< typename Class, void (Class::*Method)(void) > 
struct Call 
{ 
    Call(Class* c) 
    : m_c(c) 
    { } 

    void operator()(void) 
    { 
     (m_c->*Method)(); 
    } 

    Class* m_c; 
}; 

class A 
{ 
public: 
    void foo(void) 
    { 
     std::cout << "A::foo\n"; 
    } 
}; 

// this works 
void do_foo(A* a) 
{ 
    Call<A,&A::foo> c(a); 
    c(); 
} 

class B; 
// this doesn't compile 
extern void B::bar(void); 

// this is what i'd ultimately like to do 
void do_bar(B* b) 
{ 
    Call<B,&B::bar> c(b); 
    c(); 
} 

两个问题:

  • 可以这样做?
  • 为什么不能做到?

回答

6

你不能转发声明一个成员函数。我认为原因是,当你在一个指向B的指针上调用该函数时,编译器必须将该指针传递给该方法。但它并不知道B的确切类层次结构。该指针,从而可能的调整(由于该方法的虚拟,例如)在该点处将是不可能的。编译器也不知道该方法的可见性。毕竟,它可能是私人和你不能从外部调用它。声明该成员函数的唯一方法是定义该类,然后在该定义中声明该函数。为您解决问题的另一种方法是声明你的自由函数:

class B; 
void do_bar(B* b); 

在一个文件然后定义do_bar中,你可以放心地包括B类的定义

0

(),因为B类未定义它不能编译B ::巴。但是我认为你离开了太多问题。在这一点上:

void do_bar(B* b) 
{ 
    Call<B,&B::bar> c(b); 
    c(); 
} 

为什么你不能只是说?

void do_Bar(B* b) { 
    b->bar(); 
} 

也许如果你包括这个解释,它会更容易回答你的问题。

其次,这是为什么在需要时(如上面所示)你想通过do_bar把它称为()?为什么不让do_bar成为外部?

extern void B::bar(void); 
0

我不知道,pimpl类通常紧紧地绑定到它们的封装类。我认为有任何其他方式有点味道。这就是为什么我通常把它作为内部类的原因:

class A 
{ 
public: 
    ... 
private: 

    ... 

    class A_impl; 
    boost::scoped_ptr<A_impl> impl; 
};