1

有沒有寫一個拷貝構造一類(比方說,Copyable,即持有std::unique_ptrBase類(但一個真正的方式存儲Derived對象。是否有可能有一個複製可構造類持有std :: unique_ptr <Base>避免切片沒有基地暴露「克隆」功能?

快速測試顯示了預期的切片時,因爲Copyable不知道它的控股真正的類型,所以我想需要一個clone方法,但我不知道是否有辦法讓編譯器在一些更好的方式來處理這個

縱切代碼:?

#include <algorithm> 
#include <iostream> 
#include <memory> 
struct Base 
{ 
    Base(int i = 0) : i(i) {} 
    virtual ~Base() = default; 
    int i; 
    virtual int f() { return i; } 
}; 

struct Derived : Base 
{ 
    Derived() = default; 
    virtual int f() override { return 42; } 
}; 

struct Copyable 
{ 
    Copyable(std::unique_ptr<Base>&& base) : data(std::move(base)) {} 
    Copyable(const Copyable& other) 
    { 
    data = std::make_unique<Base>(*other.data); 
    } 
    std::unique_ptr<Base> data; 
}; 

int main() 
{ 
    Copyable c(std::make_unique<Derived>()); 
    Copyable c_copy = c; 

    std::cout << c_copy.data->f() << '\n'; 
} 

clone代碼:

#include <algorithm> 
#include <iostream> 
#include <memory> 
struct Base 
{ 
    Base(int i = 0) : i(i) {} 
    virtual ~Base() = default; 
    int i; 
    virtual int f() { return i; } 

    virtual Base* clone() { return new Base(i); } 
}; 

struct Derived : Base 
{ 
    Derived() = default; 
    virtual int f() override { return 42; } 

    virtual Derived* clone() override { return new Derived(); } 

}; 

struct Copyable 
{ 
    Copyable(std::unique_ptr<Base>&& base) : data(std::move(base)) {} 
    Copyable(const Copyable& other) 
    { 
    data.reset(other.data->clone()); 
    } 
    std::unique_ptr<Base> data; 
}; 

int main() 
{ 
    Copyable c(std::make_unique<Derived>()); 
    Copyable c_copy = c; 

    std::cout << c_copy.data->f() << '\n'; 
} 

顯然克隆代碼工作。事情是,這裏有一些我想避免的東西:

  1. raw new
  2. 需要成爲界面一部分的隨機函數。
  3. 該函數返回一個原始指針。
  4. 此類想要可複製的每個用戶都需要調用此函數。

那麼,有沒有「乾淨」的替代?

注意我想使用智能指針的所有顯而易見的原因,我只需要深刻複製std::unique_ptr。類似std::copyable_unique_ptr,將可選移動語義與深層複製拷貝構造函數結合在一起。這是最乾淨的方式嗎?或者這隻會增加混亂?

+0

'std :: copyable_unique_ptr'沒有任何意義。有一個指向可克隆對象的'std :: unique_ptr'使得它更有意義。你有什麼可能是最好的方法。但有幾點:複製構造函數是一個構造函數,所以它可以有一個成員初始化列表。 'clone'函數應該調用copy-constructor,拷貝'* this'。而派生類中的'clone'函數應該返回一個指向基類的指針。 –

+0

@Someprogrammerdude一個'copyable_unique_ptr'如何沒有意義?有很多情況下,你們都希望移動和複製數據,每當你需要它們時。當然,你需要注意'std :: move',但是不可能複製移動類型而不會弄髒接口,這似乎意味着這是一個理智的解決方案。 – rubenvb

+1

@rubenvb當用戶不期待拷貝構造函數被調用的危險是爲什麼'auto_ptr'被棄用的很大一部分。使用'copyable_unique_ptr'的效果會稍差,但它仍然會很糟糕。一個'clonable_unique_ptr'(或者在Deduplicator的答案中是'clone_ptr')不提供拷貝構造函數,但提供了一個'clone()'成員函數,實現了你希望用'copyable_unique_ptr'實現的目標,但是沒有危險。 – hvd

回答

4

您當然可以爲靜態知道如何克隆的任何對象創建clone_ptr類。

它將持有一個指向該對象的指針,以及一個指向克隆該對象的函數的指針,可能來自轉換無狀態的lambda。

相關問題