11

Objective-C 类别功能允许程序员添加原始类定义中未定义的新方法。

我可以在 C++ 上归档类似的功能(语言结构或某些技术)吗?

主要关注的是一致的方法调用语法(.->运算符)。

4

4 回答 4

7

让我们考虑扩展以下类:

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

当然我添加的函数有点傻(成员更傻,因为它不尊重原始成员的进一步更改xy),但是您应该了解我想要演示的内容。

注意构造函数B (A &&a),我称之为“提升构造函数”(这不是标准术语)。通常,B (B &&b)是一个移动构造函数,它将提供的实例的内容移动到一个即将被构造的新实例中。我使用移动语义的实例(已由另一个函数返回)移动.BBAAB

实际上,您可以提升Ato,B同时可以将 aB用作A.

与 Soonts 的回答相反,我的解决方案也适用于添加的虚拟表,因为它不依赖于不安全的指针转换。

于 2013-02-19T08:03:23.660 回答
5

另一种选择,可能不被某些人视为“干净”(尽管在我看来)但仍然完成同样的事情,是使用静态类。重要的是要记住,当我们创建一个成员函数时,幕后真正发生的是编译生成一个函数,其中对象(又名“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 中这样做,因此在这方面没有任何损失(如果您尝试使用私有或受保护的成员状态,您'已经完全错过了类别的重点)。您将无法使用 . 和 -> 运算符,但在我看来,这比派生一个新类型只是为了添加一些实用方法要好得多。

于 2014-03-22T02:08:28.723 回答
1

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;
}
于 2013-02-19T07:54:34.393 回答
0

我得到了一个几乎一致的调用约定,其中包含我大约一年前在一次闪电演讲中谈到的一个想法:

(如果没有他的评论,介绍就不那么有意义了——等到它进入 C++ 位)。

请注意,该材料并不打算被认真对待 - 尽管有些材料不可避免地有;-)

于 2014-05-26T13:55:38.527 回答