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
させることができます。B
B
A
Soonts の回答とは対照的に、私のソリューションは安全でないポインター キャストに依存しないため、仮想テーブルを追加しても機能します。
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;
}
1年ほど前にライトニング トークで話したアイデアと、ほぼ一貫した呼び出し規則が得られました。
(イントロは彼のコメントなしではあまり意味がありません - C++ ビットに到達するまで待ちます)。
この資料は真剣に受け止められることを意図したものではないことに注意してください - 必然的に、真剣に受け止められる人もいます ;-)