Objective-C 类别功能允许程序员添加原始类定义中未定义的新方法。
我可以在 C++ 上归档类似的功能(语言结构或某些技术)吗?
主要关注的是一致的方法调用语法(.
或->
运算符)。
Objective-C 类别功能允许程序员添加原始类定义中未定义的新方法。
我可以在 C++ 上归档类似的功能(语言结构或某些技术)吗?
主要关注的是一致的方法调用语法(.
或->
运算符)。
让我们考虑扩展以下类:
struct A {
int x, y;
A(int x, int y) : x(x), y(y) {}
};
您可以从此类继承或编写包含此类实例的包装类。在大多数情况下,继承是要走的路,因为包装类不是A,而是包装(包含)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
to,B
同时可以将 aB
用作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++ 位)。
请注意,该材料并不打算被认真对待 - 尽管有些材料不可避免地有;-)