【问题标题】:Polymorphic inheritance and merging of interfaces接口的多态继承与合并
【发布时间】:2015-03-23 22:52:09
【问题描述】:

如下类结构:

class interface_base
{
    public:
        virtual void f() {};
        virtual void g() {};
};

class interface_base_f : public interface_base
{
    public:
        virtual void f() {};
};

class interface_base_g : public interface_base
{
    public:
        virtual void g() {};
};

class implementation_f1 : public interface_base_f
{
    public:
        virtual void f() { cout << "f1" << endl; };
};

class implementation_f2 : public interface_base_f
{
    public:
        virtual void f() { cout << "f2" << endl; };
};

class implementation_g1 : public interface_base_g
{
    public:
        virtual void g() { cout << "g1" << endl; };
};

class implementation_g2 : public interface_base_g
{
    public:
        virtual void g() { cout << "g2" << endl; };
};

所以 interface_base_f 将决定使用什么样的 f 函数(f1f2)和 interface_base_g 会处理 g:

// Dynamic polymorphism
interface_base_f * ibf = new implementation_f1(); // Not f2!
interface_base_g * ibg = new implementation_g2(); // Not g1!

现在我想做这样的事情

interface_base * ib;
ib = ibf; // now "f" part of "ib" is "ibf" (which is "f1")
ib = ibg; // now "g" part of "ib" is "ibg" (which is "g2") (I hope ...)
ib -> f(); // will get "f1"?
ib -> g(); // will get "g2"?
ib -> f(); // will get "f1"?

但是当然

ib = ibf; 
ib = ibg; // overwrites previous instruction!

输出是

g2

ib->f()ib->g() both 成为可能的关键是什么? 不要忘记 fg 是多态对象(f 可以是 f1 f2 和 g 可以是 g1 g2)。谢谢!

【问题讨论】:

  • 如果你在基类中定义了virtual函数,你不需要在派生类中重复virtual。
  • @Christophe,这不是很好的做法吗?冗余但显式,因此很明显它是虚拟的,无需了解父类的任何信息。
  • @tyler 确实它明确且易于阅读。但它也可以隐藏错误,例如拼写错误或意外重载而不是覆盖。就我个人而言,我更喜欢明确地“覆盖”。但这是个人意见。
  • @Christohpe,这是一个很好的观点。 override 肯定更好。

标签: c++ inheritance polymorphism virtual


【解决方案1】:

可以结合virtual inheritance使用多重继承:

// these need to be redefined virtual
class interface_base_f : public virtual interface_base
{
public:
    virtual void f() {};
};
class interface_base_g : public virtual interface_base
{
public:
    virtual void g() {};
};

然后您可以定义一个类,如:

struct implementation_f1g2 : public implementation_f1, public implementation_g2 { };

然后应用这个构造:

implementation_f1g2 *pmy12 = new implementation_f1g2();
pmy12->f(); 
pmy12->g();
interface_base *pb = pmy12;
pb->f();
pb->g();

原理很简单:

  • virtual 继承意味着interface_base_finterface_base_g 都指向同一个interface_base。这也适用于它们的衍生物。
  • 多重继承意味着 implementation_f1g2 继承自 implementation_f1f()implementation_g2g()
  • 您是否只使用多重继承,您的 f1g2 对象将继承两个不同的 interface_base 子对象,每个子对象都有自己的 f() 和 g() 以及覆盖。因此,调用这些函数中的任何一个或强制转换为基类都是模棱两可的。
  • 但是将其与虚拟基础结合起来,意味着尽管有多重继承,但只有一个 interface_base 子对象。

【讨论】:

    猜你喜欢
    • 2012-12-23
    • 2016-01-05
    • 2017-09-11
    • 2016-01-05
    • 1970-01-01
    • 2021-04-15
    • 2012-05-13
    • 1970-01-01
    • 2020-12-27
    相关资源
    最近更新 更多