4

次のコードを見ました。

class NullClass {
public:
    template<class T> operator T*() const { return 0; }
};

const NullClass NULL;

void f(int x);
void f(string *p);

f(NULL); // converts NULL to string*, then calls f(string*)

Q1> 次の文が理解できません

template<class T> operator T*() const { return 0; }

特に、 とはどういう意味operator T*()ですか?

Q2>f(NULL)最終的に がトリガーされるのはなぜf(string*)ですか?

ありがとうございました

4

6 に答える 6

11

とはどういう意味operator T*()ですか?

ユーザー定義の変換演算子です。型のオブジェクトNullClassを任意のポインター型に変換できます。

このような変換演算子は、微妙で予期せぬ有害な問題を引き起こすことが多いため、ほとんどの場合は避けるのが最善です (もちろん、便利な場合もあります)。

f(NULL)最終的にトリガーするのはなぜf(string*)ですか?

NULLタイプNullClassです。に変換することはできませんintが、ユーザー定義の変換NullClass -> T*を使用して に変換できるstring*ため、void f(string*)が選択されています。

fこれは、ポインターを受け取るオーバーロードが 1 つしかないため機能することに注意してください。オーバーロードが 2 つある場合、

void f(int*);
void f(float*);

NullClass -> T*変換は と の両方に変換できるため、呼び出しがあいまいにint*なりfloat*ます。

于 2010-10-21T18:20:08.473 に答える
2

template<class T> operator T*()は、任意のからNullClassへの暗黙的な変換があることを意味します。T*T

を呼び出すときf(NULL)、コンパイラは使用するオーバーロードを決定する必要があります。どちらのオーバーロードも type のオブジェクトをとらないため、NullClassどの暗黙的な変換が存在するかがわかります。への変換はありませんが、 への変換intがあるstring*ため、変換が適用され、string*オーバーロードが呼び出されます。

于 2010-10-21T18:20:06.647 に答える
2
  1. operator Anything()「キャスト」演算子をオーバーロードします。NullClass を Anything に変換する必要があるときはいつでも、この関数が呼び出され、結果が使用されます。

    あなたの場合、 Anything はT*T が任意の型(テンプレートパラメーター)になる可能性がある場所です。つまり、NullClass は任意のポインターへのキャストをサポートします。

  2. NullClass は、 を含む任意のポインタにキャストできるため、string*. したがって、f(string*)バージョンが使用されます。

于 2010-10-21T18:20:41.910 に答える
2

Q1> 次の文が理解できません

template<class T> operator T*() const { return 0; }

特に、 とはどういう意味operator T*()ですか?

これは暗黙の変換演算子です。ここで、それが属する型のオブジェクトを暗黙的にターゲット型に変換することができT*ます。このバージョンは特別なものです。テンプレートであるため、そのオブジェクトNullClass任意のポインター型に変換できるからです。
暗黙の変換は正当な理由で嫌われます。予期しない瞬間に攻撃を開始し、オーバーロードされた関数の意図しないバージョンをコンパイラに呼び出させるという悪い癖があります。テンプレート化された暗黙的な変換演算子を持つことは、テンプレート化によって可能性が倍増するため、特に悪です。

Q2> f(NULL) が最終的に f(string*) をトリガーするのはなぜですか?

上記を参照。への変換は不可能intであるため、暗黙的な変換演算子が開始され、NullClassオブジェクトが要求された任意のポインターに変換されます。
これは意図されていると思います。通常、ポインターを整数に変換することは望ましくありません。そのため、そのクラスには任意のポインターへの暗黙的な変換がありますが、への変換はありませんint


それNullClassはそれほど悪いことではありませんが、そのNULL例は純粋な愚かさです. NULLマクロを定義する多くのヘッダーのいずれかを含めるとすぐに(0つまり、整数定数であると定義されます)、プリプロセッサはすべてのソースを踏みにじり、各使用箇所を に置き換えNULLます0。これを含めることは避けられないため、このエラーによってクラス全体がほとんど役に立たなくなります。

于 2010-10-21T18:38:01.420 に答える
1

NuLLClass は、ポインターに変換する変換関数を提供します。を呼び出すとf(NULL)、NULL を f の有効な引数に変換する方法を見つけようとします。

operator T*()NULL で呼び出すことができるため、T=string で呼び出します。これにより、 の要求が満たされf(string *)ます。NULL を int に変換する方法がないため、呼び出す関数の明確な選択肢は 1 つだけです。

于 2010-10-21T18:21:04.307 に答える
1

特に、 とはどういう意味operator T*()ですか?

type への変換演算子T*です。などの操作が可能(T*)NULLです。

Q2> f(NULL) が最終的に f(string*) をトリガーするのはなぜですか?

コンパイラは引数とメソッドのシグネチャの間で最も一致するものを探すため、この場合は を選択template<typename T> NullClass::operator T*()T=stringます。

于 2010-10-21T18:22:04.653 に答える