📄 9000.htm
字号:
<HTML>
<HEAD>
<meta http-equiv='Content-Type' content='text/html; charset=gb2312'>
<style >
.fst{padding:0px 15px;width:770px;border-left:0px solid #000000;border-right:0px solid #000000}
.fstdiv3 img{border:0px;border-right:8px solid #eeeecc;border-top:6px solid #eeeecc}
</style>
<title>
Guru of the Week:#38 多重继承 Ⅱ.
</title>
</HEAD>
<BODY>
<center>
<div align=center><div class=fst align=left><div class=fstdiv3 id=print2>
<font color="#000000" size="4"><b>
Guru of the Week:#38 多重继承 </b></font><p>/*此文是译者出于自娱翻译的gotw(guru of the week:http://www.gotw.ca/gotw/index.htm)系列文章的一篇,原文的版权是属于hub sutter(著名的c++专家,《exceptional c++》的作者)。此文的翻译没有征得原作者的同意,只供学习讨论。——译者:黄森堂*/</p>
<p><font color=#0000ff size=4><b>#38 多重继承 ⅱ.</b></font></p>
<p><b>难度:</b>8/10</p>
<p>如何你不能使用多重继承,如何模仿它吗?,不要忘记模仿可能出在客户端的自然语法。</p>
<p><b>问题:</b></p>
<p><b>1.</b>思考以下代码:</p><pre> struct a { virtual ~a() { }
virtual string name() { return "a"; } };
struct b1 : virtual a { string name() { return "b1"; } };
struct b2 : virtual a { string name() { return "b2"; } };
struct d : b1, b2 { string name() { return "d"; } };</pre>
<p>在以上示例中,如果不使用多重继承,如何写出等价的class d的代码(尽可能地相近),如何获得像d一样的效果与可用性,且在客户端的语法如何进行最小的改变。</p>
<p>开始:你要开始考虑在以下代码的情形里:</p><pre>void f1( a& x ) { cout << "f1:" << x.name() << endl; }
void f2( b1& x ) { cout << "f2:" << x.name() << endl; }
void f3( b2& x ) { cout << "f3:" << x.name() << endl; }
void g1( a x ) { cout << "g1:" << x.name() << endl; }
void g2( b1 x ) { cout << "g2:" << x.name() << endl; }
void g3( b2 x ) { cout << "g3:" << x.name() << endl; }
int main() {
d d;
b1* pb1 = &d; // d* -> b* 转换
b2* pb2 = &d;
b1& rb1 = d; // d& -> b& 转换
b2& rb2 = d;
f1( d ); // 多态(polymorphism)
f2( d );
f3( d );
g1( d ); // 切片(slicing)
g2( d );
g3( d );
// dynamic_cast/rtti
cout << ( (dynamic_cast<d*>(pb1) != 0)
? "ok " : "bad " );
cout << ( (dynamic_cast<d*>(pb2) != 0)
? "ok " : "bad " );
try {
dynamic_cast<d&>(rb1);
cout << "ok ";
} catch(...) {
cout << "bad ";
}
try {
dynamic_cast<d&>(rb2);
cout << "ok ";
} catch(...) {
cout << "bad ";
}
} </pre>
<p><b>解决方法:</b></p>
<p><font color=#999933><b>1.</b>思考以下代码:</font></p><pre><font color=#999933> struct a { virtual ~a() { }
virtual string name() { return "a"; } };
struct b1 : virtual a { string name() { return "b1"; } };
struct b2 : virtual a { string name() { return "b2"; } };
struct d : b1, b2 { string name() { return "d"; } };</font></pre>
<p><font color=#999933>在以上示例中,如果不使用多重继承,如何写出等价的class d的代码(尽可能地相近),如何获得像d一样的效果与可用性,且在客户端的语法如何进行最小的改变。</font></p>
<p>这儿有几种策略,每种都有弱点,以下这种是比较完整的:</p><pre> struct d : b1 {
struct d2 : b2 {
void set ( d* d ) { d_ = d; }
string name();
d* d_;
} d2_;
d() { d2_.set( this ); }
d( const d& other ) : b1( other ), d2_( other.d2_ )
{ d2_.set( this ); }
d& operator=( const d& other ) {
b1::operator=( other );
d2_ = other.d2_;
return *this;
}
operator b2&() { return d2_; }
b2& asb2() { return d2_; }
string name() { return "d"; }
};
string d::d2::name() { return d_->name(); }</pre>
<p>但有几个缺点:</p>
<blockquote>
<p>-提供operator b2&引起引用结束(不一致性引起)</p>
<p>-你需要调用d::asb2()来显式地使用d来像b2(在测试代码中,有一处需要改变:"b2* pb2 = &d;"改变成"b2* pb2 = &d.asb2();")</p>
<p>-dynamic_cast从d*动态转换成b2*将不能工作,(如果你使用前处理来重定义dynamic_cast,它可能会工作)</p></blockquote>
<p>有趣的是,你必须要观察d对象在内存中的布局,在多重继承中是否是相同的对象,因为我们只是尝试模仿mi,刚才没有考虑到所有语法与对语言内存提供支持的方便性。<br><br>
</p>
</DIV></div></div>
</center></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -