メソッド ポインターを作成できること、およびそれらが一般的に関数ポインターとは異なることを知っています。それらの間の変換は許可されていません。メソッド ポインターには、ポインターの調整方法などに関する多くのデータが含まれる場合がありますthis
。
特定のメソッドを実行しているコードの実際のアドレスを取得する方法を知りたいです。このアドレスはいかなる方法でも延期されませんが、特定のメソッドが属する型の識別子として使用されます - RTTI に少し似ていますが、このコードは通常 1 つのユニットでしか利用できないため、ライブラリの境界に影響されないという利点があります。 .
編集:
getType()
オブジェクトの型を返すメソッドを追加しないのはなぜですか?
自分で作成したクラスだけでなく、このように使えるようにしたいからです。私がやろうとしているのは、基本的にvariant
クラスの実装です。これは、基本的にすべてを受け入れ、特定のタイプの void* getVariantId() の特殊化が存在する場合に提供されます。
だから私は書くことができます:
template <typename T>
class getTypeId{
};
class foo{
public:
void bar();
};
// getTypeId declared but not defined for generic type T earlier...
template <>
class getTypeId<foo>{
static void* get<foo>(){
return &foo::bar;
}
};
void doSomething(myVariant var);
int main(int argc, char* argv[]){
foo f;
myVariant var = myVariant::fromType<foo*>(&f);
doSomething(f);
}
void doSomething(myVariant var){
foo* f = var.toType<foo*>(); // Returns foo object from main
int* i = var.toType<int*>(); // returns null, as var is not int* in my example.
}
fromType
を使用getTypeId
して型を表す値を取得し、 にキャストされたオブジェクトのポインタとともにそれを強化するという考え方ですvoid*
。toType
一方、`getTypeId::get から取得した値とオブジェクトに格納された値を比較します。一致する場合、内部で保持されているオブジェクト ポインターが元の型に再解釈されて返されます。
このソリューションの優れた点は、タイプ x を定義する共有ライブラリ X がある場合でも、ライブラリ X を個別に使用するライブラリ Y と Z がタイプ x が同じであることに同意することです (たとえば、Y でバリアントを作成する場合)。 Z に渡される)、X::method の原因アドレスは同じままです。Y または Z ライブラリ (ただし X ではありません!!!) の作成者として、X ライブラリで RTTI が有効になっていることを確認する必要はありません。
EDIT2:
これを実現するための実装に依存しない方法はないことがわかりました。ただし、これは作成できない機能ではなく、通常は必要ないため、存在しない機能の癖だと思います。何を達成したかったのか、どのように計画していたのか、まだ明確になっていないと思います。そう:
ライブラリとは、ここでは共有ライブラリ (.dll、.so など) を意味します。
純粋仮想ではないすべてのメソッド (定義されているすべてのメソッドを意味します) には、実装が必要です。この実装は、1 つの追加パラメーターを受け入れる関数として動作します
this
。仮想関数は、呼び出し元側でのみ異なります。X::foo
クラス X とそのメソッドを例に取りましょう。このメソッドは X 型にのみバインドされ、Y 型が継承してもこのメソッドは残るX::foo
ため、型を識別するには十分X
です。仮想メソッドのオーバーライドまたは子クラスのメソッドのカバーXchild
は、事実上、新しいメソッド Xchild::foo を新しいアドレスで定義することです。次に、Xchild::foo
を表すために使用できますがXchild
、 ではありませんX
。タイプ X (正確にはすべてのメソッド) がライブラリ libX で定義されており、libY と libZ の両方が libX を使用しており (ただし、お互いを認識していない)、X の最初のメソッドを使用して独自の目的で getTypeId を定義している場合、それを表します (これは libX 開発者に何も課さないことに注意してください)、彼らは X 型が何であるかについて合意しています。アプリケーション開発者が libY を使用してバリアントを取得し、それを libZ に渡す場合、両方が言及されたタイプを適切に認識します。
私は type-casting-variant を開発しようとはしていません - myVariant に渡された実際のポインタが Xchild だったとしても、X として保存されたバリアントは X としてのみ読み取ることができます。特定のインスタンスの最上位クラスのタイプを取得することに興味はありません-バリアントの作成に使用されたクラスだけです。