【问题标题】:How can I implement internal abstract member classes in c++?如何在 C++ 中实现内部抽象成员类?
【发布时间】:2017-05-17 08:27:02
【问题描述】:

抽象类具有内部虚函数。 抽象类可以有内部虚拟类供以后实现吗?

我尝试了以下方法:

#include <bits/stdc++.h>
using namespace std;

class C1 {
    public:
        class Child {
            int tmp;
            virtual int getint() = 0;
        };
    virtual Child getChild() = 0;
};

class C2: public C1 {
    public:
        class Child {
            int getint()
            {
                return 10;
            }
        } c;
    Child getChild()
    {
        return c;
    }
};

int main() { return 0; }

Child 是一个抽象类,将在派生类中被覆盖。并且我希望实现的Child可以用来定义一个函数。

但是,我得到了一个错误:

成员函数“virtual C1::Child C1::getChild()”的抽象返回类型无效

我不能在派生类中实现一个内部抽象类,就像实现一个虚函数一样吗?

【问题讨论】:

  • 这与内部类没有任何关系。您可以大大简化您的示例。这是minimal reproducible examplestruct foo { virtual stuff() = 0; }; foo make_foo();
  • 您不能将抽象对象作为值返回。如果这样做,客户端如何使用它,因为缺少 pure virtual 函数的实现?但是,您可以返回指向此类对象的指针。另外:在您的示例中,Child 不是抽象的。编辑它,因为有人可能不理解您的问题。
  • @MichałWalenciak 客户端调用该抽象类中定义的虚函数。
  • @ZehuiLin:我知道,但是您返回了“不完整”对象,它怎么能工作? :)
  • 在另一个类中定义的类与未定义的类之间的唯一区别是它们的名称范围。你有两个不相关的类; C1::ChildC2::Child.

标签: c++ abstract-class internal-class


【解决方案1】:

在目前的代码中,class C1::Childclass C2::Child 没有继承关系。因此,它们是完全不相关的类。即使您将它们与继承联系起来,getChild() 也不能返回 Child(值)。它可以返回Child&amp;(参考)或Child*(指针)以形成具有协方差的有效virtual方法。参考:C++ virtual function return type

使用 C++11 中可用的 override 说明符很容易捕获此类错误。

在不知道您要实现的确切上下文的情况下,可能的代码应如下所示:

class C1 {
  // ... same
  virtual Child& getChild() = 0;
  //      ^^^^^^ reference
};

class C2 : public C1 {
//         ^^^^^^ did you miss this?
public:
  class Child : public C1::Child {
  //                   ^^^^^^^^^ inheritance
    int getint() override { return 10; }
  } c;
  Child& getChild() override { return c; }
};

您的以下陈述也令人困惑:

“child是一个抽象类,后面会实现,”

virtual 方法一样,类没有这样的运行时关系。
在类的上下文中“稍后实现”​​的最佳含义是——在封闭类的主体之外实现它,例如:

class Outer { public: class Inner; };
// ...
class Outer::Inner { ... };

【讨论】:

  • 那么虚函数和抽象类又区别对待了吗?可以调用虚函数,但不能使用抽象类?
  • @ZehuiLin,我不清楚你的确切 Qn。但是,抽象类是在其主体内至少具有 1 个纯 virtual 方法的类。使用基类引用或指针调用virtual 方法。如果基类是抽象的,那么你就不能拥有它的对象。如果您不清楚,我建议您举一些例子。有关抽象类的更多详细信息,请参阅此:Abstract Class vs Interface in C++
【解决方案2】:

理论上,Abstract Classes 用于创建Interfaces。使用Interfaces,客户需要所需的功能。通过定义/实现Interfaces,服务器实现了客户端的功能。 Interface/Abstract Class 只是客户端和服务器之间需求/协议的蓝图。可以实例化实现Interface/Abstract Class 或满足功能要求的类。所以可以有很多相同的Interface/Abstract Class 的实现。现在,为了在不同时间点无缝访问相同Interface/Abstract Class 的所有这些不同实现,我们需要一种通用的方式。而这种广义的方式是通过pointer(*) or reference(&amp;) 到底层的Interface\Abstract Class

在您的代码中,C1::Child 是一个Abstract Class or Interface

因此,C1::getChild() 可以返回 Interface/Abstract C1::Child 的实现。但它不能按照上述理论解释返回Interface/Abstract C1::Child 本身的实例。因此错误。 声明C1::getChild() 的正确方法是:

  • virtual C1::Child* getChild() = 0;
  • virtual C1::Child&amp; getChild() = 0;

另外,C1::Child 可以简单地视为namespace C1 中的class,因为class 也是一种namespace,但有一些限制。

【讨论】:

    【解决方案3】:

    从您的帖子来看,您似乎有些困惑。我建议您重新阅读抽象类并自己尝试一些简单的示例。

    child是一个抽象类,后面会实现,希望 实现的 Child 可用于定义函数。

    纯虚方法(在您的示例中为virtual int getint() = 0;)并不意味着“稍后”实现。它意味着通过派生类中的覆盖方法来实现。

    例如如果你有

    class Child {
       virtual int getint() = 0;
    };
    

    你做不到

    class Child {
       virtual int getint() { return 10; }
    };
    

    也没有

    int Child::getint() { return 10; }
    

    稍后。

    你可以做的是:

    class Derived : public Child
    {
       int getint() override { return 10; }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-02
      • 1970-01-01
      • 1970-01-01
      • 2016-08-16
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 2020-10-03
      相关资源
      最近更新 更多