繁体   English   中英

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

[英]Objective-C @protocol equivalent in C++

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类委托应该实现这样的方法”的部分。

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

您的示例的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.cppB.cpp文件中同样实现A.classBSays()Bf()

在此示例中,类BDelegate是一个抽象基类(ABC),相当于您的BDelegate协议。 通过仅包含纯虚拟成员函数(前面带有关键字virtual和后缀为=0函数),它强制其子类为这些方法提供实现,就像在目标中使用@required标记(或没有标记)一样。 C协议。 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不提供它自己的覆盖, A仍会继承BDelegatefoo方法。 另一方面,使用Objective-C协议, A根本没有这样的方法,除非它本身明确地实现它。

更全面地介绍了该主题,请点击这里

通过定义抽象基类,您可以在C ++中实现基本相同。 也就是说,您只定义方法签名而不提供任何实现。 这需要任何子类来实现声明的方法。

以下是您转换为C ++的示例:

// A.h
class A : public BDelegate {
    B *b;
};

// A.m
Result A::classBsays {

}

// B.h
class BDelegate {
    virtual Result classBsays() = 0;
};

class B {
    BDelegate* delegate;
};

// B.m
void B::f {
    delegate->classBsays();
}

请注意,这可能无法编译,因为它缺少一些重要的东西。 你需要一个构造函数,传入B引用,甚至可能使用std::shared_ptr作为委托,依此类推。 但总体形状是这样的。

重要的部分是BDelegate::classBsays()的方法声明在方法签名之后具有= 0 ,并且没有实现主体。 这意味着该方法是纯虚方法,这意味着子类必须实现该方法,否则无法实例化。 (这是有道理的,否则你可能会调用一个没有实现的方法!)任何具有一个或多个纯虚方法的类本身就是一个纯虚拟类。 这正如您所描述的那样非常常用,用于定义将系统的不同部分分离的接口。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM