在Objective-C ++应用程序中接收C ++虚拟方法调用的正确方法是什么?

时间:2019-05-28 00:57:53

标签: inheritance callback objective-c++ virtual-method

我有一个可移植的C ++网络代码库,该库大量使用抽象和半抽象接口类,例如像这样的东西:

// Semi-abstract interface for any C++ object that wants to
// be notified about network events
class INetworkEventReceiver
{
public:
   INetworkEventReceiver(INetworkEventGenerator * master)
      : m_master (master)
   {
      m_master->RegisterEventReceiver(this);
   }

   virtual ~INetworkEventReceiver()
   {
      m_master->UnregisterEventReceiver(this);
   }

   // Called by our m_master object whenever a network event happens
   // Implemented by subclasses to do something useful.
   virtual void NetworkEventReceived(const NetworkEvent & event) = 0;

private:
   INetworkEventGenerator * m_master;
};

一切正常。但是,现在有兴趣通过Objective C ++在iOS应用中使用此库。

我的问题是,Objective-C ++代码实现上述NetworkEventReceived(const NetworkEvent & event)之类的“挂钩方法”的最佳方法是什么?我希望Objective-C ++类可以简单地子类INetworkEventReceiver并声明自己的虚拟方法,就像C ++子类那样,但是似乎Objective-C ++ doesn't support that。接下来的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

您可以将C ++类作为ivar嵌入到Objective-C类中。像这样:

// header:
@interface Receiver : NSObject
@end

// .mm:
// declare any methods with C++ typed parameters or return types here so the header
// can be #imported in Objective-C, not just Obj-C++. This class extension 
// can also be moved to an Objective-C++-only header if necessary to get to 
// those methods from multiple .mm files.

@interface Receiver()
- (void) receivedNetworkEvent:(const NetworkEvent& event)event;
@end


struct ConcreteReceiver : INetworkEventReceiver
{
  __weak Receiver* target;

  virtual void NetworkEventReceived(const NetworkEvent& event) override;

};

void ConcreteReceiver::NetworkEventReceived(const NetworkEvent& event)
{
  [this->target receivedNetworkEvent:event];
}


@implementation Receiver
{
  ConcreteReceiver receiverShim;
}

- (instancetype)init
{
  self = [super init];
  if (self != nil)
  {
    self->receiverShim.target = self;
  }
  return self;
}

- (void) receivedNetworkEvent:(const NetworkEvent& event)event
{
  // Do the thing
}

@end

这有点尴尬,尤其是对于较大的接口,但它可以工作。请注意,C ++对象持有对其包含Objective-C对象的__weak引用,以避免泄漏。