2013-11-26 70 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。我的目標是保持從SegmentationFaultClientconst&默認構造函數)良好的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-pointer轉換爲non-const pointer。您可以使用reference作爲PARAM,而不是const-reference,或者你可以做以下

const boost::shared_ptr<const UsedObjectInterface> used_object_; 

然而,默認刪除器爲shared_ptrdelete指針,也就是在堆未分配你的情況。在這種情況下,您應指向empty-deleter,或不要使用shared_ptr

+0

哇,我真是一個愚蠢的錯誤。是的,我只製作了智能指針「const」,而不是實際的對象。謝謝你的提示!我不完全理解你的最後一句話,你說「point'empty-deleter'」是什麼意思?你能提供更多的信息嗎? –

+0

@FlorianWolters http://www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm使用構造函數與deleter,這是函數,什麼都不做。 – ForEveR

+0

順便說一句,你有什麼建議來處理這種情況?兩種方法都會創建「原始指針」行爲。我想要一個默認的構造函數和一個完整的構造函數。默認的構造函數應該創建另一個類的實例,而完整的構造函數需要同一個類的一個參數。有沒有「最佳實踐」的C++內存所有權方法? –