To my understanding, C++ doesn't feature a mechanism to add methods to an existing class (say, QString but please don't focus on the fact that's a Qt function) as ObjC does; let's assume those new methods do not require any new member variables. Instead, the only option is to create a wrapper class (say, KString) that inherits A and adds the required method(s) (say, toFoo()).
However, this requires modification everywhere where you want to use the new method, either something like
static_cast<KString*>(ptrToQStringInstance)->toFoo()
But if there are many places like that you'd like to be able to use #define QString KString in the relevant files (or do the equivalent search/replace).
Of course then you're going to run into errors like "no viable conversion to [const] KString from [const] QString" for which you'd have to add a copy constructor like
inline KString(const QString &that)
{
*(static_cast<QString*>(this)) = that;
}
// add an assignment operator for good measure too
inline KTEStringView &operator=(const QString &other) Q_DECL_NOTHROW
{
*(static_cast<QString*>(this)) = other;
return *this;
}
My question:
- is there a well-defined and limited set of methods (independent of the parent class) that you'd have to implement (override) this way, or are you looking at overriding all methods that return a QString, trying very hard to avoid deep copies?
- is this the best approach or can you use language constructs that make this more "elegant" (e.g. using or some fancy kind of method assignment)?
Thanks!
Edit: why would you do this: when your existing class comes from an older version of a library, and you working with dependent code that would like to use things from a newer version of that library. In ObjC I have done this kind of extension regularly to add convenience methods to NSWindow or NSString so I could call them as if they were provided by the SDK, without having to cast to a dedicated child class or call a global function that takes the class instance as a parameter.
Edit2: here's another example, this time openly Qt related. It adds an alternative for QQuickItem::size() to Qt versions that do not yet have this:
template <class QtType>
class Q510QI : public QtType
{
public:
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
QSizeF size()
{
return QSizeF(QtType::width(), QtType::height());
}
#endif
};
#define Q510QIPCAST(instanceptr) static_cast<Q510QI<std::decay<decltype(*instanceptr)>::type>* >(instanceptr)
This allows me to replace foo->size() (where foo points to a QQuickItem or inherits it) with Q510QIPCAST(foo)->size().
Evidently I could have done this with a free template function (which would not have needed decltype and std::decay) but that function would need to have an explicit implementation for the newer Qt versions (call the actual QQuickItem::size() method). If I wanted to add a series of other trivial methods I'd be adding as many #if/#else/#endifs whereas here I could just add those trivial functions between that single #if/#endif.
C++ doesn't provide extension methods, as other languages (as C#) might propose.
C++ way is to add free functions or use inheritance.
Uniform function call syntax proposal might allow to have syntax you expect (with free functions way).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With