interface_cast と static_cast の違い
新しい型キャスト への移動
目次
interface_cast と static_cast の比較概要
interface_cast は、System ユニットで定義されたテンプレート関数であり、異なるインターフェイス間またはインターフェイスとオブジェクトの間でキャストを行うために使用します。static_cast は、標準の C++ キーワードであり、(interface_cast や dynamic_cast のように実行時にではなく)コンパイル時に型変換を行うために使用します。
interface_cast では、QueryInterface を呼び出して対象のインターフェイスを取得します。このキャストは実行時に行われ、背後にあるオブジェクトが対象のインターフェイスをサポートしていない場合には失敗する可能性があります。static_cast が失敗する場合は、コードのコンパイル時に失敗します(エラー E2031 が発生します)。
interface_cast が対象としているのは、Delphi クラス(TObject から派生したクラス)で実装された COM 形式のインターフェイスです。存続期間を正しく管理するには、COM 形式のインターフェイスには interface_cast を使用する必要があります。(static_cast は、存続期間管理の _AddRef/_Release の手法に対応していません。)
interface_cast を使ったインターフェイス インスタンスの取得
次のコードは、パッケージ(bpl ファイル)内でコンパイルされる Delphi ソース コードです。クラスとインターフェイスの実装が含まれています。
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.
次のコードは、先ほど Delphi で定義したクラスとインターフェイスを使用する、C++Builder コンソール アプリケーションです。この C++Builder プロジェクトは、Delphi プロジェクト(上のコードを参照)で作成されたパッケージを使ってビルドされます。
#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++ コンパイラがその階層を "見る" ことができる。(インターフェイスを実装する Delphi で書かれたクラスの階層は、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;
}