возвращая абстрактный класс из функции - PullRequest
26 голосов
/ 19 мая 2010

Можно ли вернуть абстрактный класс (сам класс или ссылку, не имеет значения) из функции?

Ответы [ 6 ]

34 голосов
/ 19 мая 2010

Вы можете вернуть указатель на абстрактный класс - при условии, что B - конкретный класс, производный от абстрактного класса A:

A * f() {
    return new B;
}

или ссылка:

A & f() {
    static B b;
    return b;
}

или умный указатель:

std::unique_ptr<A> f() {
    return std::make_unique<B>(...);
}
16 голосов
/ 19 мая 2010

Вы можете объявить тип возвращаемого значения как ссылку или указатель на абстрактный класс, чтобы его можно было присвоить ссылкам или указателям на абстрактный класс и использовать на основе его интерфейса.

Однако, вы не можете вернуть фактический экземпляр фактического абстрактного класса , потому что по определению вы не можете создать его экземпляр. Однако вы можете возвращать экземпляры конкретных подтипов, что достаточно хорошо, потому что по принципу замены вы всегда сможете использовать подтип вместо супертипа.

4 голосов
/ 19 мая 2010

Нет, но функция может иметь возвращаемый тип указателя (или ссылки) на абстрактный класс. Затем он будет возвращать экземпляры класса, производного от абстрактного класса.

3 голосов
/ 19 мая 2010

Абстрактные классы не могут быть созданы и, следовательно, не возвращены.

1 голос
/ 19 мая 2010

Шаблон проектирования Factory является примером возврата указателя на объект абстрактного класса:

class Base
{ ; }

class One : public Base
{ ; }

class Two : public Base
{ ; }

Base * Factory(unsigned int number)
{
  Base * p_item(NULL);
  switch (number)
  {
    case 1:
      p_item = new One;
      break;
    case 2:
      p_item = new Two;
      break;
    default:
      p_item = NULL;
      break;
  }
  return p_item;
}

Фактический объект абстрактного базового класса никогда не может быть возвращен, поскольку никогда не может быть экземпляр абстрактного базового класса. Указатели и ссылки на абстрактный базовый тип могут быть возвращены, как в примере выше.

Указатели и ссылки на абстрактный базовый класс, возвращаемые функцией или методом, фактически ссылаются на потомка абстрактного базового типа.

0 голосов
/ 06 июля 2011

Я знаю, что немного опоздал, но надеюсь, это кому-нибудь поможет ...

Будучи новичком в программировании на C ++, я также застрял на некоторое время над этой проблемой. Я хотел создать фабричный метод, который возвращает ссылку на абстрактный объект. Мое первое решение с использованием указателей работало хорошо, но я хотел остаться более «в стиле C ++». Вот фрагмент кода, который я написал, чтобы продемонстрировать это:

#include <iostream>

using std::cout;
using std::endl;

class Abstract{
public:
  virtual void foo() = 0;
};

class FirstFoo: public Abstract{
  void foo()
  {
    cout << "Let's go to the foo bar!" << endl;
  }
};

class SecondFoo: public Abstract{
  void foo()
  {
    cout << "I prefer the foo beer !" << endl;
  }
};

Abstract& factoryMethod(){
  static int what = 0;

  if(what++ % 2 == 0)
    return *(new FirstFoo());
  else
    return *(new SecondFoo());
}

int main(int argc, char* argv[])
{
  int howMany = 10;
  int i = 0;

  while(i++ < howMany)
  {
    Abstract& abs = factoryMethod();
    abs.foo();
    delete &abs;
  }
}

Открыто для любой критики!

...