使用姐妹继承
Posted
技术标签:
【中文标题】使用姐妹继承【英文标题】:using sister inheritance 【发布时间】:2012-04-10 05:39:50 【问题描述】:让我们假设一些(遗留)代码,不能被触及,声明
struct B
public:
void f()
;
让我们假设有
struct A
public:
virtual void f()=0;
;
是否可以在不显式调用 f() 的情况下进行 A 子类调用 B::f,即代替
struct C: public A, public B
void f()
B::f();
;
有类似的东西
struct C:virtual public A,virtual public B
;
(注意最后一个类是抽象的,因为编译器 A::f 没有定义)
【问题讨论】:
B::f()
有什么问题?这是调用B::f()
的正确方法。
想象你有 100 个函数 ;)
不,基成员函数不可能为另一个基类实现纯虚函数。那是行不通的。你所拥有的一切都很好。
好的,我有一百个函数,这和这个问题有什么关系?
我猜他想避免编写样板代码。
【参考方案1】:
直接在 C++ 中,不可能基于 B 的函数与 A 的某些隐式匹配进行多态分派。您可以使用 gccxml 或其他类似产品进行某种代码生成,但如果只有一百个函数,那么宏无论如何都可以将转发减少到单行 - 不值得引入额外的工具,除非您有成千上万的这些要做。
【讨论】:
"基于 B 的函数与 A 的一些隐式匹配进行多态调度" G++ 使用来支持所谓的“签名”:Type Abstraction using Signatures “在 GNU C++ 中,您可以使用关键字签名将完全抽象的类接口定义为数据类型。您可以使用签名指针将此抽象与实际类连接起来。(...)子类型化变得独立于继承。(...)签名允许您使用现有的类层次结构作为签名类型的实现。” @curiousguy:这是普遍的(在 gcc 3 中历史给定的删除)兴趣,但我看不出它对于做问题所寻求的或更普遍的“基于多态的调度”有什么用处B的函数与A的一些隐式匹配”你引用。鉴于signature S void f(); ; ... S* p = static_cast<A&>(this); p->f();
在功能上似乎等同于说std::function<void(void)> x = std::bind(&B::f, this); x();
- 两者似乎都比问题中的B::f();
更笨拙。不确定我是否遗漏了什么......?【参考方案2】:
实现A
,将其委托给B
:
class A_Impl : public A
public:
virtual void f()
b.f();
private:
B b;
通过从A_Impl
派生来实现C
:
class C: public A_Impl
;
或者,如果您只想在继承层次结构中显示A
,则公开派生自A
,私下派生自A_Impl
:
class C: public A, private virtual A_Impl
;
【讨论】:
【参考方案3】:你可以这样做:
void C::f()
B* b = this;
b->f();
【讨论】:
谢谢,但是我不想写每个函数的实现(另外,这个版本比我写的有什么好处?) @FabioDallaLibera:我不明白。如果您不想在C
中编写一个名为f
的函数,那么为什么要声明这样的函数?在这种情况下,C::f
的实现与您的实现之间没有区别,除了这个不使用您想要避免的 B::f
。【参考方案4】:
不,你不能那样做。从您向我们展示的 sn-p 看来,B
应该是C
的成员,通过组合而不是继承。您只需要编写一些转发函数(或自动为您生成它们的脚本)。
【讨论】:
【参考方案5】:所以,您在 A 中有 100 个纯虚函数,在 B 中实现了这些函数,并且您希望避免在 C 中编写重新实现所有这些函数来调用 B。没有办法让编译器使用 B 的实现自动地。 重新考虑继承图,而不是与编译器斗争(每次你都会输!)。也许让 B 成为 A 的子类,然后从 B 派生 C。或者将 100 个方法从 B 中分解出来并放入 A 的具体子类中。
编程是在工具提供的限制内解决问题的艺术。当您发现自己与工具不一致时,您需要重新考虑解决问题的方法或使用不同的工具。
【讨论】:
问题是说B不能被碰,所以不能让它成为A的子类,也不能把方法移出它。以上是关于使用姐妹继承的主要内容,如果未能解决你的问题,请参考以下文章