feelfree
feelfree

Reputation: 11773

Class design when one class contains an instance of another class

I give the following example to illustrate my question. Suppose Abc is a class that will use another class (Def). Assume Def is a large class with many class members (expensive for copying), it make more sense to let the pointer to a Def object be part of Abc class. Then when implementing Abc class function do1, it can refers to Def object via its pointer pDef.

class Abc
{
  public:
        Abc(Def &def)
        {
           pDef = &def;
        }
        ~Abc()
        {
         }
        void do1();
   private:
        Def *pDef;

}

However, if I implement class Abc in this way, I will have the risk that the Def pointer might be invalid. Any ideas on improving this class design? One idea I have is to use share pointer:

 class Abc
    {
      public:
            Abc(boost::shared_ptr<Def> def)
            {
               pDef = def;
            }
            ~Abc()
            {
             }
            void do1();
       private:
            boost::shared_ptr<Def> pDef;

    }

EDIT: I want to make it clear that my main purpose is to avoid the expensive copy operation when constructing class Abc. For me using the shared pointer and James Adkison's solution (accepted answer) can both solve the problem. But the effect on the expensive Def object may be different. Using shared pointer will keep many copies of the object while using James Adkison's solution will only keep one copy of Def object.

Upvotes: 2

Views: 400

Answers (3)

James Adkison
James Adkison

Reputation: 9602

Assume Def is a large class with many class members

I assume this means that it is expensive to copy the Def class. However, with C++11 you could implement move semantics for Def and keep the Abc implementation simple and efficient.

Note: This answer is based on the assumption that the only reason the question uses any pointers (smart or otherwise) is as a way to avoid expensive copies.

Example Code

class Def
{
public:
    Def() {}
    Def(const Def& other) { /* ... */ } // Copy constructor even though it's expensive
    Def(Def&& other) { /* ... */ } // Move constructor for efficiency

    Def& operator=(const Def& other) { /* ... */ } // Copy assignment
    Def& operator=(Def&& other) { /* ... */ } // Move assignment
};

Now the Def class supports copy semantics, even though copy the class may be expensive. However, it also supports move semantics to allow efficient usage when a copy isn't required.

class Abc
{
public:
    Abc() {}

    Abc(const Def& def) : mDef(def) {} // Perform an expensive copy

    Abc(Def&& def) : mDef(std::move(def)) {} // Perform a move

    // Implement any other member functions which could accept Def
    // via copy or move

private:
    Def mDef;
};

I would only advocate using std::shared_ptr if the use case is actually to support shared ownership semantics.

Upvotes: 3

Ivan Rubinson
Ivan Rubinson

Reputation: 3361

Why use a pointer if you can use a reference?

class Abc
{
public:
    Abc(Def &def) : pDef(def)
    {
    }

    void do1();
private:
    Def& pDef;
}

You aren't passing ownership, so there's no need for pointers.

Think of a reference like a pointer that can never be null.

Upvotes: 1

Sam Varshavchik
Sam Varshavchik

Reputation: 118445

This is what std::shared_ptr is for. If you use std::shared_ptr, the pointer will always be valid (as long as you follow all the very simple rules).

Upvotes: 0

Related Questions