【问题标题】:Is it possible to inherit the implementation of an interface是否可以继承接口的实现
【发布时间】:2015-12-23 08:24:45
【问题描述】:

是否可以在不为每个实现实现的情况下继承接口的实现?

上图中IBase和Ichild是只有纯虚方法的类,Base实现了IBase的方法,Child实现了IChild的方法。 现在Child 是否有可能通过Base 继承IBase 的方法的实现,从而Child 不必自己实现这些方法?

我尝试这样实现它:

struct IBase {
    virtual void do_something_Base() = 0;
};

struct IChild : public virtual IBase {
    virtual void do_something_Child() = 0;
};


struct Base : public virtual IBase {
    virtual void do_something_Base() { //implementation IBase method
        //do sth
    }
};

struct Child : public Base , public IChild {
    virtual void do_something_Child() { //implementation IChild method
        //do sth
    }
};

int main() {

    IBase* B = new Child;
    B->do_something_Base();

    delete B;

    return 0;
}

这段代码的问题在于编译器给出了警告:

警告 C4250:'Child':通过支配继承 'Base::Base::do_something_Base'

此外,程序在delete B 行崩溃。 (如果我使用IChild* B 而不是IBase* B 程序不会崩溃。为什么会这样?)

提前致谢

【问题讨论】:

标签: c++ oop inheritance interface


【解决方案1】:

我一直在一个项目中使用类似的设置,它对我有用。执行以下操作就足够了:

  1. 给IBase一个虚拟析构函数。为了能够通过指向基类的指针进行删除,虚拟析构函数是必要的。

  2. 为了安全起见,实际上也可以从IChild 派生Child。由于I-类没有数据,因此将它们用作非-虚拟基础毫无意义。

  3. 禁用警告,因为它基本上告诉编译器正在执行您希望它执行的操作(实现是从正确的基类继承的)。

【讨论】:

  • IChild 的虚拟继承有什么作用?
  • @Philinator 就像任何其他虚拟继承一样 - 确保在最派生的对象中只有一个该类型的子对象,即使有多个类派生自它。正如您目前拥有的那样,您将在Base 子对象(虚拟派生对象)中存在一个IChild,和在Child 中直接存在一个IChild(派生对象)通常)。
  • 感谢您的解释
【解决方案2】:

inherits via dominance 只是一个警告,在这里可以安全地忽略它,因为优势为您提供了正确的方法覆盖。

但是删除时的崩溃是因为通过一个类和派生类指向对象的指针不需要具有相同的表示(*)。而且您忘记在IBase 和IChild 中添加虚拟析构函数,而强烈建议将其用于可继承类,并且必须允许通过指向继承类的指针进行删除,如@Angew 所述。

如果您有充分的理由不使用虚拟析构函数(即使我无法想象),您必须在调用 delete 之前将其转换为 Child *。此外,由于IBase 是虚拟的,因此您必须使用dynamic_cast:

delete dynamic_cast<Child>(B);

另一种方法是保留通过 new 返回的原始指针并将其删除,而不是使用转换为 IBase*:

Child* C = new Child;
IBase *B = C;

B->do_something_Base();

delete C;  // deleting original pointer is safe

(*) 只是为了确定,只需添加到您的代码中:

std::cout << "IBase*:" << B << " Child*:" << dynamic_cast<Child>(B) << std::endl;

【讨论】:

  • 这对我不起作用,因为我已将 Base 和 Child 放入 dll 中,并且它们对外部不可见
  • 是的,投射它会起作用,但它非常麻烦。为IBase添加虚拟dtor是正确的解决方案。
  • @Angew:当然!我相应地编辑了我的帖子给你的功劳,但我把它留在这里,因为可以选择投射。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 2010-11-15
相关资源
最近更新 更多