Reference to abstract class as a class member

Jul 8, 2012 at 1:16pm
Hi, all!
I have the following question: suppose i have abstract class base Base and its complete implementation ImplBase (several of them); I want to use implementations of Base in some other class User as a class member. How can i do it using references (not pointers)? In particular, how can i initialize reference in constructor?

The code describing the situation is given below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Base{
public:
   virtual void someVirtualFunction() = 0
};

class ImplBase: public Base
public:
   void someVirtualFunction(){
      cout << "ImplBase ";
   }
};

class User
{
public:
   User();
private:
   Base &_ref;
};

User::User(){
//this does not work and i end up with initialized reference
   _ref = ImplBase();
}
Jul 8, 2012 at 1:29pm
Edited because I didn't like my code. :(
Last edited on Jul 8, 2012 at 2:06pm
Jul 8, 2012 at 1:55pm
I see several problems with your code.
First, is that the reference variable has to be initialized and not assigned. So I would expect a compiler error in line 23. This should be written as:
1
2
3
4
User::User():
_ref(ImplBase())
{
}

Which brings me to the second problem.

In order to use the reference to base class you need to have the actual object somewhere in memory - be it on stack or dynamically allocated. What happens in line 23 of your code is that a temporary variable is created on stack and then _ref points to it. However, this temporary variable is destroyed when constructor exits.

I am a bit confused about why do you even want to use the Base& in this case when you know exactly which implementation you will use. In this case you can just use a member variable ImplBase _impl; instead of Base& _ref;.

If you really want to have a base-class reference, then you have two options. First, is
1
2
3
4
5
6
7
8
9
10
11
12
13
class User
{
public:
   User();
private:
   Base &_ref;
};

User::User()
: _ref(*(new ImplBase()));
{
   
}

which will create an instance of ImplBase in dynamic memory. However, don't forget to destroy the object in destructor (delete &_ref;). Also to ensure correct destruction of the derived object through a pointer to the base object you need to make the destructor virtual.

The second option is to have the instance of ImplBase in your class:
1
2
3
4
5
6
7
8
9
10
11
12
13
class User
{
public:
   User();
private:
   Base &_ref;
   ImplBase _impl;
};

User::User() :
_ref(_impl)
{
}


However, again, before using the base-class reference you need to decide whether and why do you need a reference in this case.
Jul 8, 2012 at 2:15pm
> How can i do it using references (not pointers)?

Use a thin wrapper to convert a pointer to a reference, perhaps? For instance:

1
2
3
4
5
6
7
struct base // base.h
{
    virtual ~base() {}
    virtual void some_operation() const = 0 ;

    static std::shared_ptr<base> default_implementation() ;
};

1
2
3
4
5
6
7
8
std::shared_ptr<base> base::default_implementation() // base.cc
{
    struct derived : base
    {
        virtual void some_operation() const override { /* whatever */ }
    };
    return std::make_shared<derived>() ;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "base.h" // user.cc

struct user
{
    user() : pointer( base::default_implementation() ) {}
    explicit user( std::shared_ptr<base> use_this ) : pointer(use_this) {}

    void some_function() { ref().some_operation() ; /* ... */ }

    private:
        std::shared_ptr<base> pointer ;
        inline base& ref() { return *pointer ; }
        inline const base& ref() const { return *pointer ; }
};

Last edited on Jul 8, 2012 at 2:17pm
Jul 9, 2012 at 10:15am
Thanks a lot! Now it is clear
Topic archived. No new replies allowed.