2017-01-03 5 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::Child и class C2::Child не имеют отношения к наследству. Следовательно, это совершенно не связанные классы. Даже если вы связываете их с наследованием, то также getChild() не может вернуть Child (значение). Он может вернуть либо Child& (ссылка), либо Child* (указатель), чтобы сформировать действительные методы virtual с covariance. Refer: C++ virtual function return type

Такие ошибки легко пойманы с использованием спецификатора override, доступного на C++ 11.

Не зная точный контекст того, что вы пытаетесь достичь, возможный код должен выглядеть следующим образом:

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,"

Как virtual, классы не имеют таких отношений времени выполнения.
Лучшее значение «реализация позже» в контексте класса - его реализация вне тела объемлющего класса, такие как:

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

Итак, виртуальные функции и абстрактный класс и обрабатываются разными? Я могу назвать виртуальную функцию, но я не могу использовать абстрактный класс? –

+1

@ ZehuiLin, я не знаю, о вашем точном Qn. Тем не менее, абстрактные классы - это классы с по крайней мере 1 чистым «виртуальным» методом внутри своего тела. Метод '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 можно просто рассматривать как class внутри namespace C1, поскольку class также своего рода namespace с некоторыми ограничение.