Objective-C类别功能允许程序员添加未在原始类定义中定义的新方法。
我可以在C ++上存档类似的功能(语言构造或某些技术)吗?
主要关注的是一致的方法调用语法(.
要么 ->
运营商)。
Objective-C类别功能允许程序员添加未在原始类定义中定义的新方法。
我可以在C ++上存档类似的功能(语言构造或某些技术)吗?
主要关注的是一致的方法调用语法(.
要么 ->
运营商)。
让我们考虑扩展以下类:
struct A {
int x, y;
A(int x, int y) : x(x), y(y) {}
};
您可以从此类继承或编写包含此类实例的包装类。在大多数情况下,继承是一种可行的方式,作为包装类 不 一个但是它 包装 (包含)A
用C ++ 11移动语义,提升实例 A
到一个子类 B
(继承 A
)将是高效的,不需要复制实例 A
:
class B : public A {
public:
B (A &&a) : A(a), someOtherMember(a.x + a.y) {}
// added public stuff:
int someOtherFunction() const { return someOtherMember; }
private:
// added private stuff:
int someOtherMember;
};
完整代码示例: http://ideone.com/mZLLEu
当然我添加的功能有点傻(而且会员更多,因为它不尊重原始成员的进一步变化 x
和 y
),但你应该知道我想要展示什么。
注意构造函数 B (A &&a)
我称之为“促进构造函数”(这不是标准术语)。一般, B (B &&b)
是一个 移动构造函数, 哪一个 移动 提供的内容 B
实例成新的 B
即将建成。我使用移动语义来 移动 一个例子 A
(已被其他功能退回) 成 超级班 A
的 B
。
实际上,你可以推广 A
至 B
同时可以使用 B
作为一个 A
。
与Soonts的回答相反,我的解决方案也适用于添加的虚拟表,因为它不依赖于不安全的指针转换。
另一个选项,可能不被某些人视为“干净”(尽管在我看来)但仍然完成相同的事情,就是使用静态类。重要的是要记住,当我们创建一个成员函数时,幕后真正发生的是编译生成一个函数,其中对象(又名“this”)是第一个参数。因此,我们可以做同样的事情来扩展我们的类的功能而不从它衍生出来。
class Something
{
public:
Something()
~Something()
}
// In objective-c you may call this category Something+Utils
class SomethingUtils
{
// You can use a pointer, or a reference here, your call.
static int GetSomethingElse(Something *something, int parameter);
}
这将实现与类别相同的意图:扩展类对象的功能,而不必创建新的派生类。您将无法访问私有或受保护的成员函数和变量,但无论如何您无法在objective-c中执行此操作,因此在该方面没有任何丢失(如果您尝试使用私有或受保护的成员状态,则完全错过了类别的重点。你将无法使用。和 - >运算符,但在我看来,这比为了添加一些实用方法而导出一个新类型更好。
C ++具有继承性。另外,我曾多次使用以下技巧来扩展#import“progid:...”指令生成的类:
// This one is part of external framework, or auto-generated, or dllimport, or #import, etc..
class A
{
protected double m_x;
};
// This one is the extension class. Make sure you only add non-virtual methods here.
// Static methods and static data members are OK as well.
class __declspec( novtable ) B: public A
{
public:
double getSquare(){ return m_x * m_x; }
__declspec( property( get = getSquare ) ) double square;
};
// Usage example
double someFunc( A& arg )
{
B& b = static_cast<B&>( arg ); // Note we've not constructed any instance of B, just casted.
return b.square;
}
我有一个 几乎 一致的呼叫约定 我在闪电话题中谈到的一个想法 大约一年前:
(如果没有他的评论,这个介绍就没有意义了 - 等到它到达C ++位)。
请注意,这些材料并不打算被认真对待 - 尽管有些材料不可避免地存在;-)