まずは以下のコードを見て下さい。
#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未使用です。
> virtual const A &operator=(const A &rhs)
> virtual const B &operator=(const B &rhs)
この2つは引数も戻り値も異なりますから、
単に二つの異なる仮想関数があるだけです。
クラスBに const A &operator=(const A &rhs) という関数が
定義されていれば、クラスAの同関数がオーバーライドされて、
それが呼び出されるでしょう。
あ、なるほど。
分かってしまうと当たり前でしたね。
例えば
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&を返したいですが・・・
どうもありがとうございました。
解決ですね・・・
> せめて戻り値はconst B&を返したいですが・・・
C++ の規格では、オーバライドの戻り値でサブクラスを返すことが可能です。
但し、古いコンパイラであるVC6はこの標準に準拠できてません。
VC7.1ではちゃんと通ります。