2015-02-28 2 views
1

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

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

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

Это базовая структура кода, с Base быть абстрактным классом:

class Container 
{ 
    vector<unique_ptr<Base>> m_C; 

public: 
    Base& GetBase(int index) 
    { 
     return *(m_C.at(index)); //This do not compile as Base is abstract 
    } 
}; 

EDIT:

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

int main() { 
Container X; 
// Fill X here 
A tmp = X.get(10) // Let's say I want the tenth element 
} 

Компиляция на OSX с лязгом я получаю эту ошибку

variable type 'MXIO::MXEvent' is an abstract class 

edit2: Проблема решена

Я решил эту проблему. Проблема была не в том, как функция возвращалась, а в том, как я ловил возвращение. Я использовал

auto tmp = X.get(10) 

Предполагая, что автомобиль будет заботиться о принятии ссылки в то время как я использую

auto&& tmp = X.get(10) 
+0

Вы _can_ есть ссылка на абстрактный класс. Какое сообщение об ошибке вы получаете? –

+3

«Это не скомпилировать». [Вы уверены?] (Http://ideone.com/fwNSnw) Пожалуйста, предоставьте полный воспроизводимый пример. –

+0

Необработанный указатель подходит для кого-то, просто используя класс или интерфейс. Пока вы знаете, что срок службы (объекта) будет длиннее, чем используется необработанный указатель. –

ответ

1

Ваш интересный дизайн работает отлично!

Используя пример, как вы выставили ее, и с помощью простого Base:

  • в Container код компилируется без ошибок;
  • код вызова, скомпилированный также без ошибок.

Таким образом, ошибка не воспроизводится с вашим фрагментом. И ваш дизайн работает по назначению.

Реальная проблема не связана с вашим дизайном

Глядя на сообщение об ошибке, проблема, как представляется, очень разные и не связаны вообще с unique_ptr.I

Если MXIO::MXEvent является Base, в сообщении говорится, что Base является абстрактным классом. В самом деле, при добавлении чистой виртуальной функции в мой простой Base, мне удалось воспроизвести ваше сообщение об ошибке:

Base tmp = X.get(10); // tmp should be a full tmp object copy constructed from returned value 
         // But we CANNOT instantiate an abstract object !! 

Обратите внимание, что, к счастью, ваш базовый класс является абстрактным, и вы получили сообщение об ошибке. С конкретным базовым классом он бы скомпилировался, но объект был бы sliced!

Если вы не хотите потерять полиморфизм вашего абстрактного класса вы должны сделать tmp ссылку:

Base &c = test.GetBase(4); // here the reference is copied and no new object is instantiated. 
          // c still reffers to the original concrete derived object. 

Обратите внимание, что в то время как auto&& работает хорошо, Base&& не потому, что ссылка возвращается.

0

Как предложено Christophe я вывешу решение проблемы я имел в ответ:

Проблема заключалась не в том, как функция возвращавшегося свой результат, но в том, как я ловила результат.

int main() { 
Container X; 
// Fill X here 
A tmp = X.get(10) // Let's say I want the tenth element 
} 

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

В этом случае нужно поймать само возвращение по ссылке

int main() { 
Container X; 
// Fill X here 
A& tmp = X.get(10) // Let's say I want the tenth element 
} 
Смежные вопросы