interface_cast と static_cast の違い

提供: Appmethod Topics
移動先: 案内検索

新しい型キャスト への移動


interface_cast と static_cast の比較概要

interface_cast は、System ユニットで定義されたテンプレート関数であり、異なるインターフェイス間またはインターフェイスとオブジェクトの間でキャストを行うために使用します。static_cast は、標準の C++ キーワードであり、(interface_cast や dynamic_cast のように実行時にではなく)コンパイル時に型変換を行うために使用します。

interface_cast では、QueryInterface を呼び出して対象のインターフェイスを取得します。このキャストは実行時に行われ、背後にあるオブジェクトが対象のインターフェイスをサポートしていない場合には失敗する可能性があります。static_cast が失敗する場合は、コードのコンパイル時に失敗します(エラー E2031 が発生します)。

interface_cast が対象としているのは、Object Pascal クラス(TObject から派生したクラス)で実装された COM 形式のインターフェイスです。存続期間を正しく管理するには、COM 形式のインターフェイスには interface_cast を使用する必要があります。(static_cast は、存続期間管理の _AddRef/_Release の手法に対応していません。)

interface_cast を使ったインターフェイス インスタンスの取得

次のコードは、パッケージ(bpl ファイル)内でコンパイルされる Object Pascal ソース コードです。クラスとインターフェイスの実装が含まれています。

 unit MyUnit;
 
 interface
 
 type
   IMyInterface = interface(IUnknown)
     ['{D982FC08-5280-44FC-BE3B-BFD951E8BA5C}']
     procedure Welcome;
   end;
 
   TMyInterface = class(TInterfacedObject, IMyInterface)
   public
     procedure Welcome;
   end;
 
 implementation
 
 procedure TMyInterface.Welcome;
 begin
   WriteLn('Welcome!');
 end;
 
 end.

次のコードは、先ほど Object Pascal で定義したクラスとインターフェイスを使用する、Appmethod C++ コンソール アプリケーションです。この Appmethod C++ プロジェクトは、Object Pascal プロジェクト(上のコードを参照)で作成されたパッケージを使ってビルドされます。

 #include <System.hpp>
 #pragma hdrstop
 
 #include <tchar.h>
 //---------------------------------------------------------------------------
 #include <MyUnit.hpp>
 #pragma argsused
 
 int _tmain(int argc, _TCHAR* argv[]) {
 	TMyInterface *inst = new TMyInterface();
 	_di_IMyInterface intf = interface_cast<Myunit::IMyInterface>(inst); // static_cast cannot be used -- the cast cannot be done at compile time
 
 	if (intf) {
 		intf->Welcome();
 	}
 	return 0;
 }

static_cast を使ったインターフェイス インスタンスの取得(特殊な例)

インターフェイスをキャストするために static_cast を使用することは可能です。ただし、それを行ってよいのは、次のような非常に特殊な状況においてのみです。

  • C++ コンパイラがその階層を "見る" ことができる。(インターフェイスを実装する Object Pascal で書かれたクラスの階層は、C++ コンパイラからは見えません。)
  • 新しいインターフェイス インスタンスに対して _AddRef が呼び出されている。

次の例に示すのは、そのような特殊な状況(static_cast を使ってインターフェイス インスタンスを取得しても安全な場合)です。

 #include <iostream>
 #include <tchar.h>
 #include <System.hpp>
 
 // ---------------------------------------------------------------------------
 __interface __declspec(uuid("{D982FC08-5280-44FC-BE3B-BFD951E8BA5C}")) IMyInterface
     : public IInterface {
 public:
     virtual void __fastcall Welcome() = 0;
 };
 typedef System::DelphiInterface<IMyInterface>_di_IMyInterface;
 
 class TMyInterface : public TCppInterfacedObject<IMyInterface> {
 public:
     void __fastcall Welcome() {
         std::cout << "Welcome!" << std::endl;
     }
 };
 
 // ---------------------------------------------------------------------------
 int _tmain(int argc, _TCHAR* argv[]) {
     _di_IMyInterface intf(static_cast<IMyInterface*>(new TMyInterface()));
     intf->Welcome();
     return 0;
 }

関連項目