2017-01-03 3962 views
1

抽象类具有内部虚函数。 抽象类是否可以稍后实现内部虚拟类?如何在C++中实现内部抽象成员类?

我尝试以下:

#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; } 

儿童是一个抽象类,这将在派生类中推翻。我希望执行可以用来定义一个函数。

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

invalid abstract return type for member function 'virtual C1::Child C1::getChild()'

我不能实施内部抽象类中派生类,就像实现虚拟函数?

+0

这与内部类没有任何关系。你可以极大地简化你的例子。这里有一个[mcve]:'struct foo {virtual stuff()= 0; }; foo make_foo();'。 – juanchopanza

+0

您不能将抽象对象作为值返回。如果你这样做,那么客户如何使用它,因为缺少'纯虚函数'的实现?但是你可以返回指向这个对象的指针。另外:在你的例子中,'Child'不是抽象的。将其编辑为某人可能不了解您的问题。 –

+0

@MichałWalenciak客户端调用该抽象类中定义的虚函数。 –

回答

2

在本代码中,class C1::Childclass C2::Child没有继承关系。因此他们完全没有关系。即使你将它们与继承关联起来,那么getChild()也不能返回Child(值)。它可以返回Child&(参考)或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 is a abstract class, which will be implemented later,"

像方法,这些类不具有这样的运行时间关系。
类的背景下“后实施”的最好含义 - 实现它的封闭类的身体之外,如:

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

那么虚拟函数和抽象类和对待不同?我可以调用一个虚函数,但是我不能使用抽象类? –

+1

@ZehuiLin,我不清楚你的确切Qn。然而,抽象类是在其主体内至少有一个纯虚拟方法的类。使用基类引用或指针调用'virtual'方法。如果基类是抽象的,那么你不能拥有它的对象。如果你不清楚,我会建议举一些例子。有关抽象类的更多详细信息,请参阅以下内容:[C++中的抽象类与接口](http://stackoverflow.com/q/12854778/514235) – iammilind

0

从您的文章,你似乎是令人困惑的事情。我建议你重新阅读抽象类,并亲自尝试一些简单的例子。

Child is a abstract class, which will be implemented later, And I hope the implemented Child can be used to define a function.

纯虚方法(virtual int getint() = 0;在你的例子)不意味着是“后”来实现。它意味着通过派生类中的重写方法实现。

E.g.如果你有

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; } 
}; 
1

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

此外,C1::Child可以简单地看作是一个classnamespace C1,因为class也是一种namespace一些限制。