2011-10-27 52 views
4

假設你編寫了一個類A,構造函數是私有的(以防止其他人在堆棧上創建它),那麼有一天另一個開發者添加一個新的ctor,並說A(int),並且想在main()中使用:如何防止他人在堆棧上創建類的新實例?

A a(1)

在堆棧上創建它。你如何預防這種情況?

我的解決方案:

聲明的公共構造

A(void& input) 
    { 
Cerr << 「please do not create it on stack」 << endl ; 
    exit(1); 
    } 

我不知道它是正確的?

謝謝

+0

請問*你爲什麼要防止這種情況發生?給我們一個有說服力的理由,我們可以給你一個更好的實現基礎。 – Xeo

+0

@BenjaminLindley C++的一個重要特點是讓人們儘可能多地在編譯時強制執行代碼庫規則。他們都不會是完美的......你可以爭辯說,不應該爲const而煩惱,因爲可以編輯你的代碼的人可以把它const_cast去掉,但const正確性無論如何都會遇到很多錯誤。想要使用書中的每一個技巧來幫助實施代碼庫的實踐和協議並減少錯誤,沒有什麼是「愚蠢的」。對於這種情況甚至可以這樣做...查看我的答案。 – HostileFork

+0

@HostileFork:除了在C++中,只要你可以構造一個對象,只要你願意就可以構造它。 'A a;'和'std :: unique_ptr a'之間有什麼大區別?'?我都是爲了編譯執行,你提出的解決方案是有趣的,不是太侵入,但在這種情況下,它並沒有真正的工作。 –

回答

7

加入了註釋,說是這樣的:

class A 
{ 
    private: 
     // This is private on purpose to prevent allocation on the stack. 
     // We'll fire you if you ever write a new constructor that isn't private. 
     A(); 
}; 

這個評論是舌頭在臉頰(主要是),但它指出了一個重要的概念。像禁止堆棧分配這樣的代碼約定需要由同行評審強制執行。正如其他人所說,其他人理論上可以改變他們想要的代碼。但良好的同行評審流程將有助於保持這一點。恕我直言,這比一些聰明的編譯技巧,新僱員可能不一定理解的成本效益更高。

+0

事實上,特別是任何可以添加公共構造函數的人都可以明顯地修改類的任何部分,包括實現的任何機制以防止在堆棧上分配。 –

5

顯然,你不能阻止它。如果別人可以直接編輯你的代碼,那麼他們可以做任何他們想要的。

+0

當然你在一般意義上是對的......但是這個FGITW答案有多有用呢?看到我對這個問題的評論和我的回答。 – HostileFork

1

我認爲你想要的解決方案是以下步驟。

  1. 給構造函數'私人'訪問。
  2. 建立一個非成員靜態函數,它通過new或malloc創建一個實例並返回它。
  3. 使用該函數來創建類的實例。

我確定這些步驟可能是您的問題的解決方案。

8

正如其他人說,你不能阻止誰可以使它做幾乎任何編輯類人......但

...如果你想有一個稍微編譯器強制執行的方法比評論,你可以繼承一個沒有默認構造函數的類。任何撰寫構造函數的人都會(有希望)引起注意。你可以讓它的名字提醒人們採取一定的預防措施。

事情是這樣的:

class DoNotStackConstruct { 
protected: 
    DoNotStackConstruct(const char* dummy) {} 
}; 

class A : protected DoNotStackConstruct { 
private: 
    A() : DoNotStackConstruct ("PLEASE make all A constructors private!") { 
     // your code here 
    } 
public: 
    static std::tr1::shared_ptr<A> newA() { 
     return std::tr1::shared_ptr<A>(new A); 
    } 

/* ... a bunch of code ... */ 
/* ... then someone later adds the following ... */ 

public: 
    A (int i) { 
     // can't force them to make it private, but... 
     // this won't compile without mentioning DoNotStackConstruct 
    } 
}; 

一旦你開始使用C++ 11會出現 「委託構造函數」,這一招將有少一點的牙齒:

Can I call a constructor from another constructor (do constructor chaining) in C++?

然後他們將能夠委託A()而無需訪問源代碼行並複製「嘿,不要讓您的構造函數公開!」文本。但是默認情況下,他們第一次嘗試時仍會收到編譯器錯誤。

+0

'deleteA'方法是完全不必要的,構造函數是'private',而不是析構函數。 –

+0

@MatthieuM。最初我讓它返回一個shared_ptr(這是我打擾私人構造函數的唯一原因),但我只是將它進一步「簡化」。你是對的,所以我會認爲......很難決定在填寫示例時要使用多少「繪畫」,並且很難決定何時也要編譯它,實際上也是如此: -/ – HostileFork

+1

真的,這就是爲什麼你可以免費獲得代碼評論:) –

相關問題