0

C++/CLI で、私が知っていると思っていたことに反するものに出くわしました。

通常、オブジェクトを関数に渡す場合は、ドットを使用してそのメソッドにアクセスします (これはref、いくつかの追加のコンストラクターを使用して、クラスでも機能します)。

value class Value {
  void Print() { Console::WriteLine("Value"); }
};

void f(Value v) {
  v.Print();
}

また、通常、インターフェイスを介してオブジェクトを関数に渡す^と、引数にa を付け->、メソッド呼び出しで使用する必要があります。

interface class Base {
  void Print();
};

void f(Base ^b) {
  b->Print();
}

ただし、fインターフェイスに基づく制約を使用してジェネリックを作成すると、コンパイラは を使用することを主張しますが、引数リストで->は使用しないことも主張します。^

interface class Base {
  void Print();
};

generic <class T> where T : Base
void f(T t) {
  t->Print();
}

これまで、オブジェクトを直接参照する場合は.常に を使用し、ハンドルを介して参照する場合は常に を使用すると信じていまし->た。これは、を使用してオブジェクトを直接参照しているように見えます->- 何が間違っているのですか?

4

2 に答える 2

1

彼らは、C++/CLI 構文を C++ 構文と同等のものにしようとしましたが、特に成功しませんでした。ルールは.値型->メンバーへのアクセス、参照型のメンバーへのアクセスに使用することです。

一番の問題は、スタックのセマンティクスです。ハットをドロップして、参照型のローカル変数を宣言できます。その後、スコープ ブロックの最後で自動的に破棄され、コンパイラはデストラクタ呼び出しを自動的に生成します。マネージド型を C++ 型と同様に動作させ、RAII パターンを救おうとする試み。

問題の 2 番目は、値型の変数にハットを使用することをコンパイラが許可していることです。これは型の 99% が間違いであり、値がボックス化されるため、実行時に非常にコストがかかるため、特に厄介です。

ジェネリックは最終的にあいまいになり、型パラメーターは値型または参照型のいずれかになります。これにより、具体的な型が値または参照型になり、実行時まで分類されません。あなたの例ではこれが許可されていることに注意してください。値型はインターフェースを実装する場合があります。その場合のルールは、型パラメーターの変数に常にハットを付けずにコードを記述し、それらを値型として扱うことです。ただし、矢印を使用して、これらの変数を参照型参照であるかのように逆参照します。はい、非常に紛らわしいです。

于 2012-05-21T17:44:01.137 に答える
0

これまで、オブジェクトを直接参照する場合は常にを使用し、オブジェクト.をハンドルを介して参照する場合は常にを使用すると信じていまし->た。これは、オブジェクトを直接参照しているように見えます->-何が間違っているのですか?

あなたの最初の文は完全に正しいです。2番目の文については、オブジェクトに直接アクセスしていません。 Tそれ自体は、などのハンドルタイプになりますString^

余分なコピーっぽいコンストラクターを使用して、参照型のパラメーターにスタックセマンティクスを持たせるというアイデアは、言語設計と戦っています。やめることをお勧めします。.本当に演算子を使用したい場合は、管理された参照を試すことができます: void f(RefType% p)、これはインターフェースでも機能するはずです:void f2(Base% p)。ただし、参照型の複製と破棄はうまくいきません。これらの型で役立つことを行うには、コピーではなく元のオブジェクトで作業する必要があります。

于 2012-05-23T16:12:51.743 に答える