Создание объекта, переданного как объект абстрактного типа

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

#include <iostream>
using namespace std;

class abstractFoo {
public:
virtual void method() = 0;
};

Первый конкретный класс:

class concreteFoo1 : public abstractFoo {
private:
int member1;
public:
concreteFoo1() {
cout << "Constructing Foo1" << endl;
member1 = 1;
}
virtual void method() {
cout << "Foo1 member: " << member1 << endl;
}
};

Еще один конкретный класс:

class concreteFoo2 : public abstractFoo {
private:
int member1;
int member2;
public:
concreteFoo2() {
cout << "Constructing Foo2" << endl;
member1 = 2;
member2 = 3;
}
void method() {
cout << "Foo2 members: " << member1 << ", " << member2 << endl;
}
};

Что я хочу сделать, это объявить объект абстрактного типа abstractFoo и передача его в качестве параметров в функцию, которая создаст его как объект любого конкретного типа concreteFoo1 или же concreteFoo2, Сначала я использую обычный способ с указателем, переданным в параметре:

enum typeFoo {FOO1, FOO2};

void createFoo(typeFoo type, abstractFoo *foo) {
switch (type) {
case FOO1:
foo = &concreteFoo1();
break;
case FOO2:
foo = &concreteFoo2();
break;
}
}

int main() {
abstractFoo *foo = new concreteFoo1();
createFoo(FOO2, foo);
foo->method();        //Not expected result!
return 0;
}

Выход:

Constructing Foo1
Constructing Foo2
Foo1 member: 1

Проблема в том, что я не могу инициализировать foo как объект абстрактного типа, и если я инициализирую как concreteFoo1как я сделал в этом примере, foo указатель все равно будет указывать на него, даже после вызова createFoo метод.

Чтобы заставить это работать, мне сказали передать указатель на указатель в параметре:

enum typeFoo {FOO1, FOO2};

void createFoo(typeFoo type, abstractFoo **foo) {
switch (type) {
case FOO1:
*foo = new concreteFoo1();
break;
case FOO2:
*foo = new concreteFoo2();
break;
}
}
int main() {
abstractFoo *foo = new concreteFoo1();
createFoo(FOO2, & foo);
foo->method();        //Expected result
return 0;
}

Выход:

Constructing Foo1
Constructing Foo2
Foo2 members: 2, 3

Хорошо, это решение работает, но я не очень доволен им: я все еще не могу создать указатель на абстрактный тип, поэтому мне нужно создать объект, который я не буду использовать в astractFoo* foo = new concreteFoo1()и выделенная ему память никогда не освобождается, поэтому я думаю, что я закончу с утечкой памяти.

Есть ли способ создать AbstractFoo** , указатель на указатель на абстрактный тип, без создания объекта?

Итак, можете ли вы подтвердить, что двойной указатель является точным решением моей проблемы, и если да, можете ли вы ответить на две мои проблемы? Если нет, то как мне быть?

1

Решение

Если вы используете std::unique_ptr<abstractFoo>в качестве возвращаемого типа и объединения его с фабричным шаблоном вы решаете как проблемы выделения памяти, так и проблему создания.

Обратите внимание, что вам понадобится virtual деструктор в abstractFoo,

Двойной указатель — это не то, что нужно делать в C ++. Это остаток от C. Передача указателя по ссылке была бы более C ++ — иш. Не используя указатели, но вместо этого умные указатели, если даже больше C ++ — иш.

1

Другие решения

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

enum typeFoo {FOO1, FOO2};
void createFoo(typeFoo type, abstractFoo **foo) {
switch (type) {
case FOO1:
*foo = new concreteFoo1();
break;
case FOO2:
*foo = new concreteFoo2();
break;
}
}
int main() {
abstractFoo **foo = new abstractFoo*;
createFoo(FOO2, foo);
abstractFoo *foo2Ptr = *foo;
foo2Ptr->method();        //Expected result
delete foo2Ptr;
createFoo(FOO1, foo);
abstractFoo *foo1Ptr = *foo;
foo1Ptr->method();        //Expected result
delete foo1Ptr;

return 0;
}

Выход:

Constructing Foo2
Foo2 members: 2, 3
Constructing Foo1
Foo1 member: 1

Любой комментарий, особенно если я должен использовать ссылки или умные указатели?

0

По вопросам рекламы [email protected]