简体   繁体   中英

Returning a reference to an object pointed through its interface

I'm building a small framework in C++ which contains objects which are stored in an STL container as unique_ptr to their interface. I thought unique_ptr was the best choice as the container is supposed to be the sole owner of the objects.

I wanted to retrieve a reference to the pointed object from the container to pass to the caller. But when I get the pointer I need to dereference it to pass a reference of the content from my function which of course doesn't work on an abstract class.

I do not want to pass the raw pointer which would defy the whole concept I was developing. I cannot cast as I cannot know the concrete type of the stored object. The only solution it came to my mind which is reasonable enough is to store a shared pointer in the container and pass a weak pointer to the caller but if you know some other way to obtain the same result it would be great.

This is a basic code structure, with Base being an abstract class:

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 :

I'm not sure what more do you need as an example. The main will look like this

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

Compiling on OSX with clang I get this error

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

EDIT2: Problem solved

I solved the issue. The problem was not in the way the function was returning but in the way I was catching the return. I was using

auto tmp = X.get(10) 

Assuming auto would take care of taking the reference while I should have been using

auto&& tmp = X.get(10)

Your interesting design works perfectly well !

Using the example as you displayed it, and using a simple Base :

  • the Container code compiled without any error;
  • the calling code compiled also without any error.

So the error is not reproductible with your snippet. And your design works as intended.

Real problem unrelated to your design

Looking at the error message, the problem appears to be very different and not related at all to the unique_ptr . I

If MXIO::MXEvent is Base , the message says that Base is an abstract class. In fact, when adding a pure virtual function to my simple Base , I managed to reproduce your error message:

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

Note that fortunately your base class is abstract and you got an error message. With a concrete base class it would have compiled well but the object would have been sliced !

If you don't want to loose polymorphism of your abstract class you have to make tmp a reference:

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.

Note that while auto&& works well, Base&& doesn't because a reference is returned.

As suggested by Christophe I will post the solution of the problem I had as an answer:

The problem was not in the way the function was returning its result but in the way I was catching the result.

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

As Christophe pointed out the problem with this code is that tmp is not a reference to the returned object but a concrete object which of course cannot be instantiated as the base class is abstract.

In this case one should catch the return itself by reference

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM