2014-06-20 24 views
3

我目前擁有一個聲明覆制構造函數和析構函數的結構,並保留對pimpl對象的引用計數。這允許我通過價值來傳遞這個結構。我需要重構它,因爲我希望它有一個POD接口,因爲它是庫中的一部分,現在需要從使用較舊C++風格的代碼中使用。因此,我不得不刪除複製構造函數和解構器。我無法弄清楚如何在保留這個好的「按價值傳遞」這個多重所有權機制之後保留這一點。共享指針不是一種選擇,因爲該結構被用作參數,以作爲其他類的方法的參數,從庫的用戶角度看,也需要將其看作POD。暴露POD接口的引用計數結構

struct Foo { 
    Foo(const Foo&); 
    const Foo& operator=(const Foo&); 
    ~ Foo(); 
private: 
    void* pimpl; 
}; 

struct MainLibrary { 
    void DoSomething(Foo param); 
} 

用戶代碼現在是這樣的:

MainLibrary ml; 
{ 
    Foo a; 
    ml.doSomething(a); 
} 

在這一點上,一個變量可被保持在主庫中很長一段時間。爲了提高效率,Foo的內部每次都不能被深度複製,這就是爲什麼pimpl實現會保留一個引用計數器,每當Foo的實例被複制時,計數器就會增加,每當Foo的實例被銷燬時,計數器就會減少。

+0

「上午較舊的C++風格「,不支持調用你的拷貝構造函數,析構函數?這怎麼可能是C++?你應該重新回顧一下,因爲你所要求的內容是「我不能跟蹤這些對象,但是我們需要在完成所有事情時刪除其他對象」 - 沒有析構函數,你只能嘗試鏈接一個垃圾回收器。 –

+0

不,問題是我在整個庫中使用C++ 11,並且應該可以通過使用編譯時沒有C++ 11標誌的代碼鏈接到它。如果我有非POD類型,那麼當出現名稱修改錯誤時鏈接 –

+1

這是一個非常大的見解,不要問你的問題。在這種情況下,我相信你仍然可以使用你的當前設計,使用一些「粘合」數據和/或函數 - 可能使它們成爲外部「C」非成員,因此可以從任何一方調用它們,讓C + +11個代碼寄存器回調函數,所以預C++ 11端可以找到它需要的函數。還請檢查您的編譯器文檔,看看他們是否提供任何控制名稱損壞的區別.... –

回答

1

太多評論...像下面的東西。客戶端包含foo03.h,它們的使用應該不受影響。您的C++ 11實現是通過「C」層調用的。你可以找到很多的例子,如果你搜索 「將C++代碼C」 或類似....

foo03.h:

extern "C" 
{ 
    void* foo_constructor(); 
    void* foo_constructor2(void* rhs); 
    void foo_assign(void* lhs, void* rhs); 
    void foo_destructor(void* p_this); 
} 

struct Foo { 
    Foo() { p_ = foo_constructor(); } 
    Foo(const Foo& rhs) { p_ = foo_constructor2(rhs.p_); } 
    const Foo& operator=(const Foo& rhs) { foo_assign(p_, rhs.p_); return *this; } 
    ~Foo() { foo_destructor(p_); } 
    private: 
    void* p_; 
}; 

foo11.h:

// up to you whether you call this Foo (relying on mangling differences to avoid conflicts when 
// linking with C++03 objects), FooImpl, put it in a namespace ala Impl::Foo etc.. 
struct FooImpl { 
    FooImpl() { ... } 
    FooImpl(const FooImpl&) { ... } 
    const FooImpl& operator=(const FooImpl& rhs) { ... } 
    ~FooImpl() { ... } 
}; 

extern "C" 
{ 
    void* foo_constructor() { return new FooImpl(); } 
    void* foo_constructor2(void* rhs) { return new FooImpl(*(FooImpl*)rhs); } 
    void foo_assign(void* lhs, void* rhs) { *(FooImpl*)lhs = *(FooImpl*)rhs; } 
    void foo_destructor(void* p_this) { delete (FooImpl*)p_this; } 
} 
+0

非常感謝,太棒了! –

+0

@AlexDarsonik不客氣 - 希望它順利進行。 –

+0

據我所知,純C沒有函數重載(並且沒有名稱可以區分它們),所以你的兩個'foo_constructor'將會發生衝突。 – magras