2010-05-18 3 views

ответ

23

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

A * f() { 
    return new B; 
} 

или ссылка:

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

или смарт-указатель:

std::unique_ptr<A> f() { 
    return std::make_unique<B>(...); 
} 
+0

Я хочу использовать сам абстрактный класс (или его ссылку), чтобы использовать его как общую форму для других классов, которые получены из этого абстрактного класса. – cemregoksu

+0

@cemregoksu Это единственная цель для абстрактного класс. Обе приведенные выше функции иллюстрируют, как вы это сделаете в отношении возвращаемых значений функции. – 2010-05-18 21:39:34

+0

благодарит за вашу помощь. я думаю, что он работал =) – cemregoksu

3

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

+0

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

+0

Только если ссылки фактически ссылаются на экземпляр дочернего класса. –

+0

ну, а как насчет этого сценария? класс A { виртуальный void f() = 0; }; void fonk (A & a) {} работает. , так можно ли сформировать функцию, чтобы снова вернуть ссылку класса? – cemregoksu

4

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

+0

Вы имеете в виду «возвращаемый тип * ссылки на * абстрактный класс». – avakar

+0

Я не мог понять, что вы имеете в виду. можете ли вы привести небольшой пример? – cemregoksu

+1

@incrediman: тогда он ошибается. – avakar

16

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

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

1

Фабрика шаблон проектирования является примером возвращающая указатель на абстрактный объект класса:

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

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

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

-3

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

Будучи новичком в 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; 
    } 
} 

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

+3

'factoryMethod' теряет память каждый раз, когда вы его вызываете. Результат распределяется по куче, но он никогда не удаляется. (Вызывающий не может удалить его, потому что вместо ссылки указывается ссылка.) –

+0

В C++ 11 работает std :: unique_ptr. – user877329

+0

Я согласен с проблемой утечки памяти, но я только что научился импортировать определенные символы из пространства имен, используя 'using', я знал только об использовании пространства имен до сих пор! Спасибо за это @morandg! – stakx

Смежные вопросы