1

如果标题不太有意义,这里有一个精简的例子。考虑这个 myclass.h:

// Compiled with g++ 4.7 and -std=c++0x -pedantic -Wall -Wextra on Linux
class myclass {
public:
    myclass()=default;
    void init();

private:
   struct myclassImpl;
   static myclassImpl _impl;
}`   

和 myclass.cpp

#include <csignal>
using namespace std;
#include "myclass.h"

extern "C" {   
    void end_sig(int);
}   

struct myclass::myclassImpl {
    friend void end_sig(int);

    myclassImpl()=default;
    void cleanup();
}   

myclass::myclassImpl myclass::_impl;

extern "C" {
    void end_sig(int /* sig */) {
        myclass::_impl.cleanup();
    }
}

void myclass::init() {
    signal (SIGINT, end_sig);
}

void myclass::myclassImpl::cleanup() {
    // stuff...
}

如您所见,我正在尝试实现桥接或 pimpl 模式(以及单态模式,尽管我认为它与这个特定问题无关。)大多数情况下它都有效,但在这个特定的实现中而不是其他的实现中,我必须制作一个信号处理程序,它必须是外部“C”函数而不是类的方法。如果代码是这样设置的,我会收到以下错误:

In function ‘void end_sig(int)’:    
error: ‘myclass::myclassImpl myclass::_impl’ is private

我可以想到两种解决方法。

  1. 将朋友声明移到 myclass 中。
  2. 公开 _impl。

但是在这两种情况下,它都会违反接口和实现的分离吗?有没有更好的选择?

4

2 回答 2

0

我建议这样做end_sig的方法是制作myclassImpl. 它将具有 C 链接,因此可以传递给signal,并且还可以访问任何必要的内部。不需要免费的朋友功能,它仍然隐藏在 pimpl 中。

于 2013-05-10T19:53:32.600 回答
0

您已经将信号处理程序与您的实现紧密耦合,因此我将把它myclass作为您的选项 1 的朋友。

myclass另一种选择是在没有任何友谊的情况下进行公共清理功能。

于 2013-05-10T19:44:37.260 回答