2017-10-21 71 views
3

基本上我想要的是:c + +不允許棧實例,但允許新刪除

class MyClass{ 
    public: 
     MyClass() = default; 
    // what should I do? 
} 

MyClass mc; // compile time error; 
auto pmc = new MyClass; //OK 
delete pmc; //OK too 

我知道我可以把它堆只能通過隱藏的構造函數(不能現在新的類外)或隱藏的析構函數(現在不能在課程外部刪除)或隱藏兩者。如果我不想介紹一些新的命名功能,只想要新的舊的刪除功能,該怎麼辦?是否有可能(即使有黑客)?

+4

沒有,只是寫一個函數。 –

+0

請**編輯您的問題**,解釋爲什麼要禁止「MyClass」堆棧自動變量並給出更有動機的示例 –

+0

我希望'new'運算符可以重載,以便它可以返回類,並且可以接受任意數量的參數,就像構造函數一樣,這樣我們就可以編寫像:'auto px = new X(arg0,arg2,arg3);'....和'delete'就像析構函數。 – Nawaz

回答

6

我 「就像一個智能指針,而不是」 的想法:

#include <iostream> 

class MyClass_ { 
    private: 
    /**/  MyClass_(void) { } 
    /**/ ~MyClass_(void) { } 
    public: 
    void  func(void) const { std::cout << "Hello" << std::endl; } 

    friend class MyClass; 
} ; 

class MyClass { 
    public: 
    /**/  MyClass(void) : p(new MyClass_) { } 
    /**/ ~MyClass(void) { delete p; } 

    // Tricky implementation details follow... 
    // The question in all cases is, who owns the MyClass_ that has been 
    // allocated on the heap? Do you always allocate a new one, and then 
    // copy the guts? (That might be expensive!) Do you change ownership? 
    // Then what about the other MyClass? What does it point to? 
    // Or do you share ownership? Then you need to ref-count so you don't 
    // delete too soon. (And this whole thing turns into an ordinary 
    // shared_ptr<MyClass_>) 

    /**/  MyClass(const MyClass &o) { } 
    /**/  MyClass(MyClass &&o) { } 
    MyClass &operator=(const MyClass &o) { } 
    MyClass &operator=(MyClass &&o) { } 

    MyClass_ * operator->(void) { return p; } 
    const MyClass_ * operator->(void) const { return p; } 

    private: 
    MyClass_ *p; 
} ; 

int 
main(int, char **) 
{ 
    MyClass a;     // this will be destroyed properly 
    MyClass *b = new MyClass; // this will leak if you don't delete it 

    a->func(); 
    (*b)->func(); 

    return 0; 
} 
+3

這很聰明。它說明了這個類只能在堆上生活的事實實際上並不是用戶需要意識到的。他們關心的是實例化一個對象。通過隱藏堆分配作爲實現細節,如果需要,還可以保留包裝器對象的值語義。 – ComicSansMS

+1

要麼正確執行五項規則,要麼包括需要完成的評論(或刪除它們)。否則,在複製對象時會出現未定義的行爲。 – Rakete1111

+1

^那。如果你不打算寫他們,至少要提到他們 –

0

這聽起來像不是你想要的,而是將它包圍在另一個類中。通過這種方式,您可以強制將存儲分配到堆中,並將這些細節遠離API用戶。

+0

你能否提供代碼和更清晰的解釋......圍繞着,你的意思是讓它成爲嵌套類嗎?它將如何幫助? – Phil1970

0

通常的方法是讓你的構造函數private,並添加一些static成員函數(你可以稱之爲工廠或製作函數)返回一個指針。

,以便類會是什麼樣子

class MyClass{ 
    private: 
     MyClass() = default; 
    public: 
     static MyClass* make() { return new MyClass; }; 
    // what should I do? 
} 

,你會代碼:

auto mc = MyClass::make(); 

其他地方(的new MyClass代替)

等,但要注意的rule of five,並考慮使用(作爲MyClass::make的返回類型)<memory> header中的一些smart pointer

你也可以擁有自己的一元operator ->operator *和自己variadic templates通過std::make_shared靈感定義自己的智能指針類...

只想好老new和delete

在真正的C++ 11中,這是令人不悅的,可能被認爲是糟糕的風格。你應該避免在庫外使用明確的new,並採用一些智能指針的編碼方式。

+0

你可以使用智能指針的想法,而不是引用計數對象,你只是使用指針來確保所有的底層對象都分配在堆上。 (指針本身可以被分配或自動分配,這並不重要。) –