読者です 読者をやめる 読者になる 読者になる

bcc32.exeの拡張構文"__property"と仮想関数

C++Builder Tips

アクセスメソッドは多用しても、プロパティは標準C++に無いからあまり使っていなかったけど、「シンタックスシュガー」としては激しく便利。 ただ、仮想関数との兼ね合いがちょっと気になったので試してみた。

//---------------------------------------------------------------------------
#include <iostream>
#pragma hdrstop
#include <tchar.h>
//---------------------------------------------------------------------------
class CBase
{
public:
  CBase() : m_Attribute(0)
  {
  }
  virtual ~CBase()
  {
  }
protected:
  int m_Attribute;
public:
  // アクセスメソッド(ゲッター)
  virtual int GetAttribute() const
  {
    return m_Attribute;
  }
  // アクセスメソッド(セッター)
  virtual void SetAttribute(int Value)
  {
     m_Attribute = Value;
  }
  // bcc32の拡張構文を使用した「プロパティ」の定義
  __property int Attribute = {read = GetAttribute, write = SetAttribute};
};

class CFoo : public CBase
{
  void SetAttribute(int Value)
  {
    // 継承クラスのセッターでは負数を受け付けない
    if (Value < 0) Value = 0;
     m_Attribute = Value;
  }
};

#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
  // 基底クラスのプロパティ
  CBase Base;
  Base.Attribute = 100;
  std::cout << "Base.Attribute = " << Base.Attribute << std::endl;

  // 派生クラスのプロパティ
  CFoo Foo;
  Foo.Attribute = 200;
  std::cout << "Foo.Attribute = " << Foo.Attribute << std::endl;
  Foo.Attribute = -1;
  std::cout << "Foo.Attribute = " << Foo.Attribute << std::endl;

  // 多態でプロパティ
  CBase* pBase = new CFoo();
  pBase->Attribute = 300;
  std::cout << "pBase->Attribute = " << pBase->Attribute << std::endl;
  pBase->Attribute = -400;
  std::cout << "pBase->Attribute = " << pBase->Attribute << std::endl;
  delete pBase;

  return 0;
}
//---------------------------------------------------------------------------

出力結果

Base.Attribute = 100
Foo.Attribute = 200
Foo.Attribute = 0
pBase->Attribute = 300
pBase->Attribute = 0

C++Builder(bcc32.exe)の拡張構文"__property"はDelphiC#Rubyのプロパティ(属性)をC++でサポートする拡張構文。C++Builderにおける__propertyの具体的な使い方と概要はここで。
基底クラスでアクセスメソッドを仮想関数にしておけば、派生クラスのプロパティもオーバーライドした関数を呼び出してくれる。