前置声明方法指针

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();
}

有两个问题:

  • 这能做到吗?
  • 为什么不能做到?
3个回答

6
您无法提前声明成员函数。我认为原因是当您在指向 B 的指针上调用该函数时,编译器必须将 this 指针传递给该方法。但此时它还不知道 B 的确切类层次结构。因此,在该点上不可能进行对该指针的可能调整(例如,由于该方法是虚拟的)。编译器也不知道该方法的可见性。毕竟,它可能是私有的,您不能从外部调用它。唯一的方式是定义类,然后在该定义内声明该成员函数。解决问题的另一种方法是声明您的自由函数:
class B;
void do_bar( B* b );

然后在一个文件中定义do_bar函数,在该文件中可以安全地包含类B的定义。

0

它无法编译B::bar(),因为类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;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接