2013-11-26 6 views
1

저는 C++을 처음 사용하고 포인터/참조와 관련하여 문제가 있습니다. 코멘트가 기본 생성자는 "즉시"제거 스택에 객체를 생성하기 때문에, SegmentationFaultClient 클래스의 implementaton은 단순히 잘못 말하는 것처럼원시 포인터/참조에서 스마트 포인터 만들기

#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; 
} 

: 다음 예는 내 문제를 반영한다. 따라서 포인터를 사용하는 클래스 CorrectClient을 생각해 냈습니다. 내 목표는 SegmentationFaultClient (const& 기본 생성자)에서 좋은 API (공개 부스트 없음)를 유지하는 것입니다. 위의 예는 하지 작업을 수행하고 다음과 같은 오류와 함께 종료 :

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 

그래서 내 질문은 : 그것은 스마트 포인터에 원시 포인터 *을 변환 할 수 있습니까? 그렇다면 가장 좋은 방법은 무엇입니까? 내 코드에 다른 문제가 있으면 알려 주시기 바랍니다!

답변

2

const-pointernon-const pointer으로 변환하려고했습니다. 대신 const-reference의, PARAM으로 reference 사용하거나이

const boost::shared_ptr<const UsedObjectInterface> used_object_; 

그러나, shared_ptr에 대한 기본-Deleter가이 delete 포인터가 될 것입니다 다음을 수행 할 수 있습니다, 그 힙에 할당되지 않은 사건이다. 이 경우 empty-deleter을 가리 키거나 shared_ptr을 사용하지 않아야합니다.

+0

와우, 나에게서 어리석은 실수. 예, 저는 실제 객체가 아닌'const' 스마트 포인터만을 만들었습니다. 힌트를 주셔서 감사합니다! 나는 당신의 마지막 문장을 완전히 이해하지 못한다. 추가 정보를 제공해 줄 수 있습니까? –

+0

@FlorianWolters http://www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm deleter가있는 생성자를 사용합니다. 함수는 아무 것도 수행하지 않습니다. – ForEveR

+0

Btw, 그런 상황을 다루기위한 귀하의 추천은 무엇입니까? 두 접근법 모두 "원시 포인터"동작을 생성합니다. 나는 기본 생성자와 완전한 생성자를 원한다. 기본 생성자는 다른 클래스의 인스턴스를 만들어야하지만 전체 생성자는 동일한 클래스의 인수를 하나 가져야합니다. "최고의 연습"C++ 메모리 소유권 접근법이 있습니까? –