问题
Objective-C category feature allows programmer to add new method which was not defined in original class definition.
Can I archive similar functionality (language construct or some technique) on C++?
Major concern is consistent method calling syntax (.
or ->
operator).
回答1:
Let's consider the following class to be extended:
struct A {
int x, y;
A(int x, int y) : x(x), y(y) {}
};
You can inherit from this class or write a wrapper class which contains an instance of this class. In most cases, inheritance is the way to go, as a wrapper class isn't an A but it wraps (contains) an A.
With C++11 move semantics, promoting an instance A
to a subclass B
(inheriting A
) will be efficient and doesn't require to copy the instance 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;
};
Full code with example: http://ideone.com/mZLLEu
Of course the function I added is a bit silly (and the member even more, since it doesn't respect further changes of the original members x
and y
), but you should get an idea of what I want to demonstrate.
Note the constructor B (A &&a)
which is something I call "promote constructor" (this is not a standard term). Normally, B (B &&b)
is a move constructor, which moves the contents of the provided B
instance into a new B
about to be constructed. I use the move semantics to move an instance of A
(which has been returned by another function) into the super-class A
of B
.
Effectively, you can promote A
to B
while making it possible to use a B
as an A
.
In contrast to Soonts' answer, my solution also works with added virtual tables, since it doesn't rely on unsafe pointer casting.
回答2:
Another option, which may not be viewed as "clean" by some (though it is in my opinion) but still accomplishes the same thing, is using a static class. It's important to remember that when we create a member function, what's really happening behind the scenes is that the compile generates a function where the object (aka "this") is the first parameter. So, we can do the same thing to extend our class's functionality without deriving from it.
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);
}
This will accomplish the same intent as a category: You extend the functionality of your class object, and you don't have to create a new derived class. You will not be able to access private or protected member functions and variables, but you can't do that in objective-c anyway, so there's nothing lost on that front (and if you are trying to use private or protected member state, you've missed the point of categories entirely). You wouldn't be able to use the . and -> operators, but in my opinion, that's a much better compromise than deriving a new type just to add some utility methods.
回答3:
C++ has the inheritance for that. In addition, I've used the following trick a few times to extend classes generated by #import "progid:..." directive:
// 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;
}
回答4:
I got a nearly consistent calling convention with an idea I talked about in a lightning talk a year or so ago:
(the intro makes less sense without he commentary - wait til it gets to the C++ bit).
Note that the material was not intended to be taken seriously - although some, inevitably, have ;-)
来源:https://stackoverflow.com/questions/14952141/objective-cs-category-like-construct-or-technique-in-c