C#のクラス拡張メソッドのような元のクラス定義(クラスと対応する.hファイルを含むコンパイル済み.lib)を変更せずに、クラスに新しいメソッドを追加する方法はありますか?C++クラス拡張
C++クラス拡張
答えて
いいえ、これはC++では実行できません。
あなたはこのような何かを達成したいならば、あなたは2つのオプションを持っている
-
あなたは、このオプションがある場合は、クラスが書き込まれていないかもしれないとして、それは法的ではないかもしれません(クラスから継承することができ
- 同じインターフェイス+新しいメソッドを持ち、拡張したいラッパークラスに独自のラッパークラスを作成することができます。
私は委任アプローチを推奨します。
申し訳ありませんが、コードがobjに入ったら、それを変更することはできません。これをVCで行うことができれば、部分クラスは既にサポートされています。しかし、1つの例外があります。演算子メソッドは、グローバル関数を使って拡張できます.cout < <がSTLでどのように実装されているかとよく似ています。
C#クラスの拡張メソッドは、ほとんどが構文的な砂糖です。自由な関数(つまり、最初のパラメーターとしてクラスへの参照または定数参照を持つ関数)を使用して同じ機能を得ることができます。これはSTLでもうまくいくので、あなたのクラスではいかがですか?
あなたができることを確認:それはしかし、最良の方法だというわけではありません
template <typename Ext>
class Class: public Ext { /* ... */ };
。
一般的にはありません。ただし、ライブラリで拡張機能が必要なクラスのインスタンスが作成されず、クラスのインスタンスを作成して拡張機能を必要とするアプリケーション内のすべての場所を変更できる場合は、次のような方法があります。
- クラスのインスタンスを必要とするすべての場所で呼び出され、インスタンスへのポインタを返すファクトリ関数を作成します(のデザインパターンファクトリ、...)。
- 必要な拡張子を持つ派生クラスを作成します。
- ファクトリ関数が、元のクラスではなく、派生クラスを返すようにします。
例:あなたは拡張子にアクセスする必要があるときはいつでも
class derivedClass: public originalClass { /* ... */};
originalClass* createOriginalClassInstance()
{
return new derivedClass();
}
- 、あなたはもちろんの派生クラスにオリジナルキャストを、キャストする必要があります。
これは、グレンが提案する「継承」メソッドの実装方法です。 Glenの "同じインターフェースを持つラッパークラス"メソッドも理論的には非常にいいですが、あなたのケースではうまく動作しないようにプロパティが少し異なります。
これには1つの方法があります。それはあなたの要件を少し緩和することです。 C++では、クラスのインターフェイスはメンバー関数だけでなく、で動作するすべての関数で構成されています。
つまり、パラメータとしてクラスを与えることができる非メンバ関数は、そのインタフェースの一部と考えるべきです。
たとえば、std::find()
またはstd::sort()
は、クラスのメンバーではないにもかかわらず、std::vector
のインターフェイスの一部です。
この定義を受け入れると、非メンバ関数を追加するだけでクラスを拡張できます。
バイナリ形式のクラスファイルにメソッドやデータを物理的に追加することはできません。ただし、拡張クラスを作成することによって、そのクラスのオブジェクトにメソッドとデータ(機能と状態)を追加できます。これは単純ではなく、Meta-Object-ProtocolとInterfaceに基づくプログラミングが必要です。あなたはC++でこれを達成するために多くのことをする必要があります。なぜなら、これは、そのままの状態でのReflectionをサポートしていないからです。このような実装では、元のクラスオブジェクトポインタを介して新しい拡張クラスによって実装されたインタフェースをクエリすると、メタオブジェクト実装は実行時に作成する拡張クラスのメタクラスオブジェクトを介してそのインタフェースポインタを返します。 これはカスタマイズ可能な(プラグインベースの)ソフトウェアアプリケーションフレームワークの数です。ただし、オブジェクト関係が記述されている辞書を使用してすべてのクラスのメタオブジェクトをインスタンス化し、元のクラスオブジェクトと拡張クラスオブジェクトの正しいインタフェースポインタを与えるためには、他の多くのMOPメカニズムが必要です。ダッソー・システムズのCATIA V5は、CAA V5というアーキテクチャーで書かれており、既存のコンポーネントを拡張することができます。
C++ではフリー関数を使用できますが、多くの関数を一緒にネストすると拡張メソッドがうまく機能することがあります。このC#のコードを見てみましょう:
var r = numbers.Where(x => x > 2).Select(x => x * x);
我々はそれが次のようになりフリー機能を使用してC++でこれを書くためにした場合:
auto r = select(where(numbers, [](int x) { return x > 2; }), [](int x) { return x * x; });
だけでなく、これは読みにくいですが、それは難しいです書く。これを解決する一般的な方法は、パイプライン機能と呼ばれるものを作成することです。これらの関数は、|
パイプ演算子(実際には演算子)をオーバーロードすることによって作成されます。したがって、上のコードは次のように書くことができます:
auto r = numbers | where([](int x) { return x > 2; }) | select([](int x) { return x * x; });
読み書きがはるかに簡単です。多くのライブラリは、範囲に対してパイプ機能を使用しますが、他のクラスにも拡張できます。 Boostはrangeライブラリでそれを使用し、pstade ovenはそれを使用し、このC++ linqライブラリもこのライブラリを使用します。
独自の配管機能を記述したい場合は、方法を説明してください。hereしかし、他のライブラリーは、機能アダプターを提供しています。 Pstadeの卵はpipable adaptor、linqは少なくとものアダプタを提供して、範囲のパイプライン機能を最小限にします。
struct contains_t
{
template<class Range, class T>
bool operator()(Range && r, T && x) const
{ return (r | linq::find(x)) != boost::end(r); };
};
次に、あなたはこのように静的初期化を使用して機能を初期化します:
range_extension<contains_t> contains = {};
次に、あなたがあなたのを使用することができますLINQ、あなたは最初だけで、このような関数オブジェクトとして、あなたの関数を作成を使用して
if (numbers | contains(5)) printf("We have a 5");
- 1. PHPクラス拡張
- 2. 拡張クラス
- 3. デルファイ拡張クラス
- 4. クラスをobjective-cで拡張する
- 5. font-awesomeクラスへのC#ファイル拡張子
- 6. 拡張NSManagedObjectクラスのラッパーメソッドobjective-c
- 7. MembershipUserクラスの拡張
- 8. コアデータメソッドのクラス拡張
- 9. クラス拡張とフレームワーク
- 10. PHPクラスの拡張
- 11. UIComponent拡張クラスにUIComponent拡張クラスが表示されない
- 12. 変換クラスの拡張性(拡張メソッドとParitalクラス)
- 13. C++、PHPの拡張
- 14. 拡張SNMPエージェントC#
- 15. PHP拡張クラスの変数
- 16. PHPクラスの拡張とオブジェクト
- 17. クラスとインスタンスの拡張
- 18. YUI3プラグインとクラスの拡張
- 19. Javaクラスの拡張子
- 20. 動的に拡張JSクラス
- 21. 拡張GroovyのStringクラス
- 22. 拡張クラスからクラス名を取得
- 23. Javaのデザイン:クラスとクラスの拡張子
- 24. 抽象クラスの拡張クラスとDAO
- 25. 静的クラスを拡張する拡張メソッド
- 26. 拡張クラス内の拡張メソッド自体を使用して
- 27. ヘッダーを変更せずにC++クラスを拡張する
- 28. 文字列クラスに拡張メソッドを追加する - C#
- 29. SwiftでObj-Cクラス拡張を使用していますか?
- 30. C#でのスタイルクラスの拡張 -
今後の参考として、これは「Monkey patching」と呼ばれています。 – LiraNuna