1
votes

I am pretty new to C++ and have a problem regarding pointers/references. The following example reflects my problem:

#include <iostream>

#include "boost/make_shared.hpp"
#include "boost/utility.hpp"

class UsedObjectInterface {
 public:
  virtual int data() const = 0;
};

class UsedObject : public UsedObjectInterface {
 public:
  UsedObject() : data_(42) {
  }

  explicit UsedObject(int value) : data_(value) {
  }

  int data() const {
    return data_;
  }

private:
  const int data_;
};

class BaseClient : private boost::noncopyable {
public:
  virtual const UsedObjectInterface& used_object() const = 0;
};

class SegmentationFaultClient : public BaseClient {
 public:
  // This can't work, since the object is deleted immediately.
  // IMHO only the following two solutions can work:
  // 1. The member attribute is not a reference (not possible with an abstract class, we lose the advantages of polymorphism).
  // 2. The member attribute is a pointer.
  SegmentationFaultClient() : used_object_(UsedObject()) {
  }

  explicit SegmentationFaultClient(const UsedObjectInterface& used_object)
      : used_object_(used_object) {
  }

  const UsedObjectInterface& used_object() const {
    return this->used_object_;
  }

 private:
  const UsedObjectInterface& used_object_;
};

class CorrectClient : public BaseClient {
 public:
  CorrectClient() : used_object_(boost::make_shared<UsedObject>()) {
  }

  explicit CorrectClient(const boost::shared_ptr<UsedObjectInterface> used_object)
      : used_object_(used_object) {
  }

  // TODO Is it possible to change this to a const&, so at least the interface
  // is the same as in SegmentationFaultClient? Then the above constructor can
  // be deleted.
  explicit CorrectClient(const UsedObjectInterface& used_object)
      : used_object_(&used_object) {
      // TODO How-to convert a raw pointer to a smart pointer?
  }

  const UsedObjectInterface& used_object() const {
    return *this->used_object_;
  }

 private:
  const boost::shared_ptr<UsedObjectInterface> used_object_;
};

int main() {
  SegmentationFaultClient segfault_client;
  const UsedObjectInterface& a = segfault_client.used_object();
  std::cout << a.data() << std::endl;

  // Correct, but how to make this work with a const& constructor?
  const UsedObject first_object;
  CorrectClient correct_client(first_object);
  const UsedObjectInterface& b = correct_client.used_object();
  std::cout << b.data() << std::endl;
}

As the comments say, the implementaton of the SegmentationFaultClient class is simply wrong, since the default constructor creates an object on the stack, which is "immediately" removed. Therefore I came up with the class CorrectClient, which uses pointers. My goal is to keep the nice API (no public Boost) from SegmentationFaultClient (const& default constructor). The above example does not work and terminates with the following error:

invalid conversion from 'const UsedObjectInterface*' to 'boost::shared_ptr<UsedObjectInterface>::element_type* {aka UsedObjectInterface*}' [-fpermissive]
 explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete

So my question is: Is it possible to convert a raw pointer * to a smart pointer? If so, what is the best way to do that? If you see any other problems with my code, please let me know, too!

1

1 Answers

2
votes

Problem is, that you are trying to convert const-pointer to a non-const pointer. You can use reference as param, instead of const-reference, or you can do following

const boost::shared_ptr<const UsedObjectInterface> used_object_;

However, default-deleter for shared_ptr will be delete pointer, that is in your case not allocated on heap. You should point empty-deleter, or not use shared_ptr in this case.