c++ - C++ 中的 Objective-C @protocol 等价物

标签 c++ objective-c delegates

A 类有一个 B 类的实例作为成员。有时 B 类的实例想要与 A 类对话。在 Objective-C 中我可以这样做:

// A.h
@interface A : NSObject <BDelegate>
@property (nonatomic, retain) B *b;
@end 

// A.m
- (void) classBsays {

}


// B.h
@protocol BDelegate
- (void) classBsays;
@end

@interface B : NSObject
@property (nonatomic, assign) id<BDelegate> delegate;
@end

// B.m
@implementation B
- (void) f {
    [delegate classBsays];
}
@end

我在 C++ 中使用类 B 的 void 指针做了类似的事情。但这错过了“类 B 的委托(delegate)应该实现这样那样的方法”的部分。

如何在C++中模仿Objective-C的协议(protocol)?

最佳答案

您的示例的 C++ 等效项如下所示:

// A.hpp
#include "B.hpp"

class A : public BDelegate {
    public:
        void classBSays ( ) { }
        B* b;
};

// B.hpp
class BDelegate {
    public:
        virtual void classBSays( ) = 0;
};
class B {
    public:
        void f ( ) { delegate->classBSays( ); }
        BDelegate* delegate;
};

请注意,为了简洁起见,我在这里使用了成员函数的内联实现 - 您同样可以单独实现 A.classBSays()B.f() A.cppB.cpp 文件(如果需要)。

在此示例中,BDelegate 类是一个抽象基类 (ABC),等同于您的 BDelegate 协议(protocol)。通过仅包含纯虚成员函数(以关键字 virtual=0 后缀开头的函数),它强制其子类为这些方法提供实现,就像使用@required 标签(或无标签)在 Objective-C 协议(protocol)中执行。 BDelegate 仅包含此类函数这一事实使其成为 ABC。

您可以通过在 ABC 中为函数指定一个空主体来模拟 Objective-C @optional 标记,这意味着不需要子类来实现它(因为它在 ABC 中实现).例如,您可以通过如下修改 BDelegate 来模拟可选的 foo 方法:

@protocol BDelegate
- (void) classBsays;
@optional
- (void) foo;
@end
// Is approximately equivalent to:
class BDelegate {
    public:
        virtual void classBSays( ) = 0;
        virtual void foo( ) { }
};

使用该定义,类 A 可以根据需要选择是否为 foo 提供定义。但是请注意,这并不完全等同于 Objective-C 的 @optional 表示法,因为 A 仍将继承 BDelegatefoo 方法,如果它不提供它自己的覆盖。另一方面,对于 Objective-C 协议(protocol),A 根本没有这样的方法,除非它自己明确地实现它。

可获得对该主题的更全面介绍 here .

关于c++ - C++ 中的 Objective-C @protocol 等价物,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18752500/

相关文章:

c++ - 遍历 map 的 map 和删除项目的最佳模式是什么?

iPhone 应用程序崩溃(仅限 iOS4)

ios - 根据控制台,委托(delegate)似乎没有工作

c# - 委托(delegate)中的协方差,有什么例子吗?

ios - Swift 委托(delegate)和可选

c++ - 何时使用 dynamic_cast 的可接受示例?

c++ - 用 C++ 实现 Mongoose 服务器

c++ - "std::cout << std::endl;"如何编译?

iOS:检查系统是否有足够的内存

ios - iPad 上的 iPhone 应用程序 : drawViewHierarchyInRect causes glitch