Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

請問大家關於 operator = 在繼承體制下的使用問題

0 views
Skip to first unread message

魚之聲

unread,
Jun 8, 2000, 3:00:00 AM6/8/00
to
嗯,有耐心的網友們就請仔細看一下我的問題吧。這個問題有點長,因為
我必須把它好好描述,才能讓你們知道我到底遇到什麼困難。
------------------------------------------------------------------

假設有base class如下:

class A
{
public:
A() { x = 0; }
A& operator = (const A &rhs) { x = rhs.x;}
private:
int x;
};

當然這種小場面是不需動用到operater = 的,在此只是為了舉例明確簡潔。

現在有個derived class如下:

class B : public A
{
public:
void do_something() {//.....}
};

B 並沒有多出任何data member。

現在當然可以進行以下的動作:

A *ptr1 = new B;
A *ptr2 = new B;
*ptr1 = *ptr2;

我們知道這樣會去引發 B 的base class,A,中的operator = ,而且在operator = 的
parameter list中,雖然型態是const A&,但是仍然可以傳B 進來,因為reference 就
像是個"寫得好看一點的pointer"。在此, [1;33m我再強調這裡用reference的好處,因為我的
問題和這個有關。 [m

接著考慮另一個derived class:

class C : public A
{
public:
C() { y=0;}
void do_something_else() {//.....}
private:
int y;
};

喔喔,現在因為C有多出自己的data member了,所以如果類似上面的程式碼:

A *ptr1 = new C;
A *ptr2 = new C;
*ptr1 = *ptr2;

這時base class的operator = 勢必無法提供我們的需求,因為還有 y 這個data
member需要拷貝。

於是我們第一個會想到要重載一個operator =,但是由於現在我的程式用到的是
"用base class的pointer指向derived class的object",所以應該要使用多型來
處理了。所以我把class A的A& operator =前面加上virtual。

所以,這個問題變成下面這樣:

class A
{
public:
A() { x=0;}
[1;33mvirtual [m A& operator = (const A &rhs) {x=rhs.x;}
private:
int x;
};

class C : public A
{
public:
C() {y=0;}
[1;31mA& operator = (const A &rhs) {//....} [m
private:
int y;
};

看到C 所重載的operator =函式原型(首先,函式原型當然要和class A中宣告的一
樣呀,不然就不是重載了),發現到一個重要問題: [1;33m無法在class C的operator =
的定義中寫下:

y = rhs.y; [m

因為rhs的型態可是const A&,就好像無法從base class的pointer直接去取用
derived class object的data member一樣。

有什麼解決方法嗎??

目前我只想到改成

virtual A* operator = ( [1;33mA* rhs [m)

這樣的話,在C重載的 A* operator = (A* rhs)中,就可以做down cast的動作來
處理這個問題。

可是,自己覺得這樣做滿爛的,因為在寫接下來的程式碼時,勢必寫成:

A *ptr1 = new C;
A *ptr2 = new C;
*ptr1 = ptr2;

這樣太奇怪了。

有沒有人有辦法parameter的型別仍然是用傳reference的方式,但是仍然可以處理
這個問題的??
==========================================================================

以上是我的思路啦,如果在中間有就想錯的話,就請大家指教了。
--
※ Origin: 楓橋驛站<bbs.cs.nthu.edu.tw> ◆ From: 202.39.11.114

天天天藍

unread,
Jun 9, 2000, 3:00:00 AM6/9/00
to
【 在 Jejj...@bbs.cs.nthu.edu.tw (魚之聲) 的大作中提到: 】
: 嗯,有耐心的網友們就請仔細看一下我的問題吧。這個問題有點長,因為


This should be a rather normal problem. But it takes me some time
to solve it. Probably I did not have the problem before. Let me
use the example to show it. The details again can be found in
the book "More Effective C++", by Scott Meyers


class Base {

private :
int x ;

public :
Base( int a ) : x(a) {}

inline int getx() const { return x ; }
inline int setx( int a ) { x = a ; }

virtual Base& operator=( const Base& foo ) {
x = foo.x ;
return *this ;
}

virtual ostream& print( ostream& out ) const {
out << x ;
return out ;
}

friend ostream& operator<<( ostream& out , const Base& foo ) {
return foo.print(out) ;
}

};


class Derived : public Base {

private :
int y ;

public :

Derived( int a , int b ) : Base(a) , y(b) {}

virtual Base& operator=( const Base& foo ) {
setx( foo.getx() ) ;
/*
The following statement is the key but ugly. There
should be other nice ways.
const_cast : cast away to const
dynamic_cast : down cast the Base pointer to Derived
*/
y = (dynamic_cast<Derived*>(const_cast<Base*>(&foo)))->y ;
return *this ;
}

virtual ostream& print( ostream& out ) const {
out << getx() << " , " << y ;
return out ;
}

};



main() {

Base foo(3) ;
cout << foo << endl ;

Derived bar(4,5) ;
cout << bar << endl ;

Base *pt1 = new Derived(6,7) ;
Base *pt2 = new Derived(9,1) ;

cout << *pt1 << endl ;
cout << *pt2 << endl ;

*pt2 = *pt1 ;

cout << *pt1 << endl ;
cout << *pt2 << endl ;

}


The result is

3
4 , 5
6 , 7
9 , 1
6 , 7
6 , 7


--

> 吳維漢 -- wei...@math.ncu.edu.tw
> 中央大學數學系

--
[m [1;35m※ [1;33m發信站 [m[ [1;37;44m中央數學 織夢天堂 bbs.math.ncu.edu.tw [m]
‧ [1;32mFROM [m[ [1;37;44mziyou.math.ncu.edu.tw [m] [m

0 new messages