How can I implement internal abstract member classes in c++?

386 Views Asked by At

An abstract class has internal virtual functions. Can an abstract class have internal virtual classes to be implemented later?

I tried the following:

#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 is an abstract class which will be overrode in derived classes. And I hope the implemented Child can be used to define a function.

However, I got an error:

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

Can't I implement an internal abstract class in derived classes, just like implementing a virtual function?

3

There are 3 best solutions below

2
On BEST ANSWER

In the present code, class C1::Child and class C2::Child have no inheritance relationship. Hence they are totally unrelated classes. Even if you relate them with inheritance, then also getChild() cannot return Child (value). It can return either Child& (reference) or Child* (pointer) to form a valid virtual methods with covariance. Refer: C++ virtual function return type

Such errors are easily caught by using override specifier available in C++11.

Without knowing the exact context of what you are trying to achieve, the possible code should look like this:

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

Also your below statement seems confusing:

"Child is a abstract class, which will be implemented later,"

Like virtual methods, the classes don't have such runtime relationships.
The best meaning of "implementing later" in the context of class is -- implementing it outside the body of the enclosing class, such as:

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

From your post you seem to be confusing things. I suggest you get a re-read on abstract classes and try some simple examples yourself.

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

A pure virtual method (virtual int getint() = 0; in your example) is not meant to be implemented "later". It's meant to be implemented by an override method in a derived class.

E.g. if you have

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

you cannot do

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

nor

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

at a later time.

What you can do is:

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

Theoretically, Abstract Classes are used for creating Interfaces. Using Interfaces, clients demand the required functionality. By defining/implementing Interfaces, servers fulfill the client's functionality. Interface/Abstract Class are simply blueprint of requirement/agreement between client and server. The classes which implement the Interface/Abstract Class or fulfills the functionality requirement can be instantiated. So there can be many implementation of the same Interface/Abstract Class. Now in order to access all these different implementation of the same Interface/Abstract Class seamlessly at different point of time, we need a generalized way. And this generalized way is via pointer(*) or reference(&) to the underlying Interface\Abstract Class.

In your code C1::Child is an anAbstract Class or Interface.

So, C1::getChild() can return an implementation of the Interface/Abstract C1::Child. But it cannot return an instance of the Interface/Abstract C1::Child itself as per above theoretical explanation. And hence the error. Proper way to declare C1::getChild() would be:

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

Also, C1::Child can be simply seen as a class inside namespace C1, since class is also a kind of namespace with some restriction.