Абстрактный класс имеет внутренние виртуальные функции.
Может ли абстрактный класс иметь внутренние виртуальные классы, которые будут реализованы позже?
Я попробовал следующее:
#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; }
ребенок абстрактный класс, который будет переопределен в производных классах. И я надеюсь, что реализовано ребенок может использоваться для определения функции.
Однако я получил ошибку:
недопустимый абстрактный тип возврата для функции-члена ‘virtual C1 :: Child C1 :: getChild ()’
Разве я не могу реализовать внутренний абстрактный класс в производных классах, так же, как реализовать виртуальную функцию?
В настоящем коде class C1::Child
а также class C2::Child
не имеют наследственных отношений. Следовательно, они совершенно не связаны между собой. Даже если вы связываете их с наследованием, то также getChild()
не может вернуться Child
(значение). Может вернуть либо Child&
(ссылка) или Child*
(указатель), чтобы сформировать действительный virtual
методы с ковариационная. См: Тип возвращаемой виртуальной функции C ++
Такие ошибки легко обнаруживаются при использовании 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; }
};
Также ваше приведенное ниже утверждение выглядит запутанным:
«Ребенок — это абстрактный класс, который будет реализован позже»
подобно virtual
методы, классы не имеют таких отношений во время выполнения.
Лучшее значение слова «реализация позже» в контексте класса — это реализация вне тела включающего класса, например:
class Outer { public: class Inner; };
// ...
class Outer::Inner { ... };
Теоретически, 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
с некоторыми ограничениями.
Из вашего поста вы, кажется, путаете вещи. Я предлагаю вам перечитать абстрактные классы и попробовать несколько простых примеров.
Ребенок — это абстрактный класс, который будет реализован позже, и я надеюсь
реализованный дочерний элемент может использоваться для определения функции.
Чисто виртуальный метод (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; }
};