2

Assume I have the following abstract class and use it as an "interface" in C++:

class IDemo
{
  public:
    virtual ~IDemo() {}
    virtual void Start() = 0;
};


class MyDemo : IDemo
{
  public:
    virtual void start()
    {
      //do stuff
    }
};

Then in the class that need to have a handle to the interface (concrete class through injection):

class Project
{
  public:
    Project(IDemo demo);

  private:
    IDemo *_demo;
};

My intention is to assign concrete Demo class through the constructor of Project. This code doesn't compile since IDemo can't be instantiated. Any suggestions? Thanks in advance.

superhero
  • 6,281
  • 11
  • 59
  • 91
Icerman
  • 1,099
  • 4
  • 14
  • 30

5 Answers5

6

Try:

 Project::Project(IDemo* demo)
     : _demo(demo)
 {}

But If the demo object is never going to change for the lifetime of the project then I prefer to pass by reference:

class Project
{
    public:
        Project(IDemo& d)
          : demo(d)
        {}
    private:
        IDemo&  demo;
};

Then use it like this:

int main()
{
    MyDemo    demo;
    Project   project(demo);
}
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 1
    @all, first of all, it is amazing to get 4 answers after a bathroom break! @Martin, I agree that in my case, passing by reference is more suitable. Any use cases you found for using a pointer instead? – Icerman Apr 07 '11 at 18:20
  • @Icerman: No there should never be a reason for using RAW pointers. If you want something that is dynamically allocated it should be contained within some form of smart pointer (otherwise there is no ownership semantics). – Martin York Apr 08 '11 at 19:54
  • 1
    What if what's being passed in wasn't dynamically allocated? I could just as easily create a type and pass in the address of it like: Demo d; Project project(&demo). I'm passing in the pointer to demo but demo wasn't dynamically created. From hearing that storing class variables by reference can causes issues, this seems valid. – user441521 May 16 '14 at 19:38
  • @user441521: Then you pass by reference (this indicates that lifetime is longer and is not dynamically allocated). – Martin York May 16 '14 at 22:10
  • @user441521 I know it is a bit late in the day, but this whole scheme depends on `MyDemo` being an `IDemo`, which it isn't due to the private inheritance. So, it wouldn't work as is. – juanchopanza Jul 04 '17 at 05:58
3
Project(IDemo demo);

Should be

Project(IDemo *demo);
Eelke
  • 20,897
  • 4
  • 50
  • 76
2

Must be:

class IDemo
{
    public:
        virtual ~IDemo() {}
        virtual void Start() = 0;
};


class MyDemo : public IDemo
{
    public:
        virtual void Start()
        {
            //do stuff
        }
};

...............................

class Project
{
    public:
        Project(IDemo* demo);
    private:
        IDemo *_demo;
};

Note

(1) class MyDemo : public IDemo

(2) IDemo* demo already suggested earlier (or you may also use IDemo& demo but it is conventional to use pointer to interface).

(3) virtual void Start() {...} instead of start (identifiers are case-sensitive).

Serge Dundich
  • 4,221
  • 2
  • 21
  • 16
  • if you have some links, I am interested in see these links supporting using pointers vs. reference. Thanks, – Icerman Apr 07 '11 at 18:30
  • @Icerman: If you consider usual functions and usual class-typed parameters it is natural to use (1) const reference for mandatory input parameters, (2) non-const reference for mandatory output parameters, (3) const pointer for optional input parameter (then you may pass 0), (4) non-const pointer for optional output parameter. All those are simple parameters you are willing to use during function call (i.e. not to be stored by pointer). Interface is different thing. (See next comment) – Serge Dundich Apr 07 '11 at 19:11
  • @Icerman: There are also objects passed to the function with full or partial ownership - objects that may be used after the function returns (interface is this king of object). It is natural to pass them as pointers to make it more explicit that this pointer may be stored. Of course we might pass them by reference too but it is much less intuitive that someone is going to take the address and store it. – Serge Dundich Apr 07 '11 at 19:24
1

Without seeing the exact compiler warning I suggest you change

Project(IDemo demo);

To

Project(IDemo *demo);
nathan
  • 5,513
  • 4
  • 35
  • 47
1

It depends. If the concrete Demo object is not owned by Project, use a reference:

class Project
{
    public:
        Project(IDemo &demo);
    private:
        IDemo &_demo;
};

If you want ownership, use a boost::shared_ptr:

class Project
{
    public:
        Project(boost::shared_ptr<IDemo> demo);
    private:
        boost::shared_ptr<IDemo> _demo;
};

Project project(boost::make_shared<Demo>());

In C++0x you can also use an std::unique_ptr, if you do not want shared ownership.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283