2013-11-21 2 views
1

У меня есть абстрактный базовый класс в C++ и вам нужно создать массив для хранения объектов, которые являются его подклассами. Я использую указатели на подклассы, так как каждый член массива должен быть одного размера. В настоящее время я заявляю и инициализации мой массив так:Инициализация массива подклассов абстрактного базового класса в C++

BaseClass *array[]; 
... 
array = 
{ 
    &SubClass1(...), 
    &SubClass2(...), 
    ... 
    &SubClass3(...) 
}; 

Это дает мне следующее, когда я пытаюсь скомпилировать:

warning: taking address of temporary 
error: too many initializers for ‘BaseClass* [0]’ 

Что такое правильный способ сделать это?

ответ

2

На той же линии и не принимает адрес временного, как вы делаете в &SubClass1(...),. Что-то, как:

BaseClass *array [] = { new SubClass(...), new SubClass2(...), .... }; 

Но этот дизайн пахнет немного, как, не зная, как сделать factory.

Как вы не используете std::shared_ptr или std::unique_ptr для управления указателем, не забудьте указать delete им! (спасибо @dasblinkenlight)

+0

Я пробовал это, но это дает мне «ошибку: слишком много инициализаторов для« BaseClass »[0]». – PandaConda

+0

Я только что протестировал аналогичную вещь под g ++ 4.8 и без ошибок ... http://ideone.com/phWplC – Johan

+0

К сожалению, я застрял в gcc 4.4.7. Неужели это не работает? – PandaConda

1

Эти SubClass1(...) являются временными объектами, и если элемент управления выходит за пределы области действия, они будут разрушены, и все указатели array будут висящим указателем на неверные адреса.

Вы можете сделать эти объекты в рамках array «s, чтобы убедиться, что эти объекты и этот массив имеет такой же срок службы:

SubClass1 class1 (...); 
SubClass2 class2 (...); 
SubClass3 class3 (...); 
BaseClass *array[] = 
{ 
    &class1(...), 
    &class2(...), 
    ... 
}; 

Также вы можете использовать смарт-указатель:

std::unique_ptr<BaseClass> array[] = 
{ 
    std::unique_ptr<BaseClass>(new SubClass1), 
    std::unique_ptr<BaseClass>(new SubClass2) 
}; 
+0

Я не думаю, что 'std :: unique_ptr' будет хорошо, если это своего рода заводская конструкция, потому что вы не можете их скопировать ... Но если это просто для доступа, это сработает. – Johan

3

Вы не можете сделать он с временными параметрами - вы должны распределять свои объекты статически, динамически или помещать их в автоматическое хранилище.

Чтобы выделить объекты статически, выполните следующие действия:

static SubClass1 s1(..); 
static SubClass2 s2(..); 
static SubClass3 s3(..); 
BaseClass *array [] = { &s1, &s2, &s3 }; 

Если выделить их динамически, рекомендуется использовать vector<shared_ptr<T>> вместо «сырых» указателей для автоматизации Deallocation:

vector<shared_ptr<BaseClass>> data = { 
    make_shared<SubClass1>(...) 
, make_shared<SubClass2>(...) 
, make_shared<SubClass3>(...) 
}; 
+0

'std :: make_shared (...)' было бы даже лучше! – Johan

+0

@Johan Это правда, спасибо! Теперь это исправлено. – dasblinkenlight

+0

Спасибо. Я попробую этот метод. Так нет ли способа сделать это, не сохраняя каждый объект (указатель на каждый) в отдельной переменной вне массива? Я хотел бы иметь возможность просто редактировать содержимое этого массива, чтобы изменить его содержимое без необходимости изменять что-либо вне его. – PandaConda

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