メタクラスとは何かについて少し読んでいますが、C++ で実現できるかどうか知りたいです。
Qt ライブラリが MetaObjects を使用していることは知っていますが、それを実現するために C++ の拡張機能を使用しています。C++で直接可能かどうか知りたいです。
ありがとう。
C++ には (Python/Objective-C の方法ではなく) メタクラスのサポートが組み込まれていませんが、メタクラスの動作を手動で模倣できます。基本は非常に単純です。対応するクラスを作成および操作できる、より長い寿命を持つ追加のクラス (Singleton、静的オブジェクト、またはConstruct On First Use Idiom ) を作成します。(Objective-C では、メタクラスには通常、「静的」メンバー変数、メモリ割り当て/割り当て解除ルーチンなどが含まれます)。
Qt が行ったことは、メタクラスの概念を採用し、何らかの形式のリフレクション (およびそれをサポートしていないシステムでは RTTI) をサポートできるように修正したことです。これを実装するには、多くのマクロ マジックまたはカスタム コンパイラ (使用することを選択したものなど) が必要になります。
ただし、一般に、通常のメタクラスが提供する機能のほとんどは、C++ 言語によって既に提供されています。形が違うだけ。実際、メタオブジェクトが必要な唯一の理由は、リフレクションの目的のためです。このドキュメントで概説されているように、C++ でリフレクションを実装するにはさまざまな方法があります。
それに加えて、あなたが実際にObjective-Cスタイルのメタクラスシステムに設定されている場合、それを行うライブラリを私は知りませんが、存在する可能性は非常に高いです. 一方、独自のロールを作成することもそれほど難しくありません。
Gamma 氏らによる本「Design Patterns」にあるパターンのいくつかは、メタクラスの概念と同様の機能を備えています。たとえば、「戦略」パターンを使用すると、作成時にオブジェクトの動作をカスタマイズできます。手紙と封筒の慣用句は、もう 1 つの密接な一致です。ただし、クラスへのインターフェイスをカスタマイズすることもできません。
COM では、IDispatch インターフェイスを使用して、実行時にオブジェクトにメソッド/属性を動的に追加できます。ただし、標準の C++ メソッド呼び出しを放棄することを意味します。すべての呼び出しは同じメソッドを通過します。このメソッドは、インデックスまたは文字列キーをユーザー管理のメソッド/プロパティ テーブルに取り込み、すべてのパラメーターをオブジェクトの配列として渡す必要があります。
これらの 2 つの手法を使用すると、メタクラスの柔軟性を得ることができますが、構文の良さやランタイム/コンパイラのヘルプがないため、はるかに困難な作業になります。
デイブ
メタクラスの作業定義が「インスタンス化自体がクラスである言語エンティティ」である場合、ジェネリックは C++ のメタクラスです。
#include <iostream>
using namespace std;
template <typename T>
class Meta {
public:
Meta(const T&init) : mData(init) {}
// ...
private:
T mData;
};
int main(int, char **) {
cout << "The size of Meta<double> is " << sizeof(Meta<double>) << endl ;
return 0;
}
最後から 2 番目の行で Meta<double> を使用すると、コンパイラは Meta<double> クラスをインスタンス化する必要があります。sizeof 演算子は Meta で動作するため、これが単なるセマンティック シュガーではなく、クラスがインスタンス化されていることが示されます。Meta 型のオブジェクトがインスタンス化されていなくても、プログラムは完了しています。
メタクラスを作成することは可能ですが、C++ はそうではなく、実行時の柔軟性ではなく、静的にコンパイル時に基づく実装に関するものです。
いずれにせよ、メソッドを含むメタクラスが必要か、データを含むメタクラスのみが必要かによって異なります。データ クラスは、boost::any のような Boost コンストラクトで実装できます。また、メソッドを含むクラスが必要な場合は、boost::bind を使用できます。メソッドをオブジェクトにバインドするか、COM オブジェクトのような単一エントリ ポイント インターフェイスを使用して独自に実装できます。
ただし、「実際の」C++ の方法はジェネリックを使用することであり、最高のパフォーマンスを得るためにコンパイル時にすべてを決定できます。
正直なところ、実行時の柔軟性が本当に必要なシステムはいくつか見たことがありますが、ほとんどの場合、オブジェクトは同じクラスで生まれて死ぬか、少なくともその寿命の 95% を 1 つのオブジェクトとして費やすのに十分なシステムを見たことがありません。彼らが工場から出てきたらクラス。
そのため、多くの場合、ランタイム メタクラスに多額の費用を支払っていることに気付きます。もちろん、これにより開発者のパフォーマンスが向上するという考え方もありますが、多くの場合、コードの各行は、それを記述するのにかかった時間の数億倍もハードウェア上で実行されます。したがって、コンパイル時および実行時のクラスは、前払いまたは永久にリースするものと考えることができます。個人的には前払いがいいと思います。
恐れてはいけません...少なくともネイティブではありません。
Java の場合と同様に、メタクラスを持つには、通常、クラスを表すランタイム オブジェクトが必要です。
C++ では、クラスにはランタイム表現がありません。それらの症状は、仮想テーブルなどで発生します。しかし、多くの点で、それらは C 関数のように動作し、すべての OOP はほとんどグルー コードとして機能します。
そうは言っても、他の言語でメタクラスを使用して実装したい多くのものに対する OOP パターンがあります。独自のオブジェクト システムを「シミュレート」することもできます。