operator=のオーバーライドについて

[戻る]
C++初心者 2005/09/30(金) 12:20:47
まずは以下のコードを見て下さい。

#include <iostream>

using namespace std;

class A {
  int num_a;
public:
  A(int a) : num_a(a) {}
  virtual ~A() {}

  virtual const A &operator=(const A &rhs)
  {
    if(this == &rhs) return *this;
    num_a = rhs.num_a;
    return *this;
  }

  virtual void OutNum() const
  {
    cout << "num_a = " << num_a << endl;
  }
};

class B : public A {
  int num_b;
public:
  B(int a, int b) : A(a), num_b(b) {}

  virtual const B &operator=(const B &rhs)
  {
    if(this == &rhs) return *this;
    A::operator=(rhs);
    num_b = rhs.num_b;
    return *this;
  }

  virtual void OutNum() const
  {
    A::OutNum();
    cout << "num_b = " << num_b << endl;
  }
};

int main()
{
    A *pA = new B(3, 4);
    B *pB = new B(1, 2);

    pA->operator=(*pB);
    pA->OutNum();

    delete pA;
    delete pB;

    return 0;
}

上のコードを実行すると

  num_a = 1
  num_b = 4

と表示されます。
pAはB型のオブジェクトを指しており、実際OutNum()で二つの値が表示されています。
しかし num_b = 4 ということはB::operator=()が呼ばれていないようです。
operator=()は仮想関数ですのでB::operator=()が呼ばれるはずなのですが・・・
operator=()は仮想関数とはならないのでしょうか?

環境はVC++6.0SP6 WinXPSP2 MFC未使用です。

dairygoods 2005/09/30(金) 12:33:04
>  virtual const A &operator=(const A &rhs)
>  virtual const B &operator=(const B &rhs)

この2つは引数も戻り値も異なりますから、
単に二つの異なる仮想関数があるだけです。

クラスBに const A &operator=(const A &rhs) という関数が
定義されていれば、クラスAの同関数がオーバーライドされて、
それが呼び出されるでしょう。

C++初心者 2005/09/30(金) 12:56:03
あ、なるほど。
分かってしまうと当たり前でしたね。

例えば

const A &B::operator=(const A &rhs)
{
  A::operator=(rhs);
  B *pB = dynamic_cast<B *>(&rhs);
  if(pB != NULL) num_b = pB->num_b;
  return *this;
}

とでもすれば良いのでしょうか?
せめて戻り値はconst B&を返したいですが・・・

どうもありがとうございました。

C++初心者 2005/09/30(金) 12:56:22
[[解決]]
解決ですね・・・

Ban 2005/09/30(金) 13:05:25
> せめて戻り値はconst B&を返したいですが・・・

C++ の規格では、オーバライドの戻り値でサブクラスを返すことが可能です。
但し、古いコンパイラであるVC6はこの標準に準拠できてません。
VC7.1ではちゃんと通ります。

古いスレッドには追加発言できません。