Differences between interface_cast and static_cast

From Appmethod Topics
Jump to: navigation, search

Go Up to New-style Typecasting

Comparative Overview of interface_cast and static_cast

interface_cast is a template function defined in the System unit that is used to cast between different interfaces or between interfaces and objects. static_cast is a standard C++ keyword that is used to perform type conversions at compile time (not at run time, like interface_cast and dynamic_cast).

interface_cast calls QueryInterface to get the target interface. The cast is done at run time and can fail if the underlying object does not support the target interface. If a static_cast fails, then the code does not compile (an error is issued: E2031).

interface_cast is targeted for COM-style interfaces implemented by Object Pascal classes (TObject derived classes). You should use interface_cast with COM-style interfaces to ensure correct lifetime management. (static_cast does not participate in the _AddRef/_Release approach to lifetime management.)

Obtaining an Interface Instance with interface_cast

The following code listing represents Object Pascal source code that is compiled in a package (bpl file). It contains the implementation of a class and an interface.

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.

The following code listing represents a Appmethod C++ console application that uses the class and the interface defined previously in Object Pascal. The Appmethod C++ project is built with the package resulted from the Object Pascal project (see the previous listing).

#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;
}

Obtaining an Interface Instance with static_cast (Particular Case)

It is possible to use static_cast to cast interfaces. But you can do this in very particular situations:

  • The C++ compiler can "see" the specific hierarchy. (The hierarchy of classes written in Object Pascal that implement interfaces is not visible to the C++ compiler.)
  • _AddRef is called for the new interface instances.

The following example illustrates such a particular case (where static_cast can be used to obtain an interface instance safely):

#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;
}

See Also