C++如何禁止掉對象的複製操作

最容易想到的是將拷貝構造函數與賦值函數聲明爲private。但是,private只是說外部不能直接調用,但是可以間接通過類的成員函數與友元函數對其訪問。那麼怎麼辦呢?

----》在類中,允許聲明函數,但是,可以不用實現該函數,這是合法的。那麼即使是在public中聲明函數,但是不實現,那麼調用這個函數也是會出錯的。


那麼好了我們可以特性一起使用,將拷貝構造函數與賦值函數,聲明爲private,並且不給出實現這樣就實現了類複製的完全禁止。

用戶代碼中的複製嘗試將在編譯時標記爲錯誤,而成員函數與友元函數中的複製嘗試將在鏈接時出現錯誤。

上面介紹的這種技術在你熟悉的std::iostream類中已經得到了很好的應用,諸如ios_base、basic_ios和sentry,都採用這樣的方式不允許複製操作。


Boost爲我們提供了另一種解決方式,這種方式更加完美,因爲它可以將鏈接錯誤提前到編譯時,畢竟早一點發現錯誤比晚發現要好。

特意聲明一個不可複製的類boost::noncopyable

#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED  
#define BOOST_NONCOPYABLE_HPP_INCLUDED  
  
namespace boost {  
  
//  Private copy constructor and copy assignment ensure classes derived from  
//  class noncopyable cannot be copied.  
  
//  Contributed by Dave Abrahams  
  
namespace noncopyable_  // protection from unintended ADL  
{  
  class noncopyable  
  {  
   protected:  
      noncopyable() {}  
      ~noncopyable() {}  
   private:  // emphasize the following members are private  
      noncopyable( const noncopyable& );  
      const noncopyable& operator=( const noncopyable& );  
  };  
}  
  
typedef noncopyable_::noncopyable noncopyable;  
  
} // namespace boost  
  
#endif  // BOOST_NONCOPYABLE_HPP_INCLUDED  


爲了禁止拷貝對象,我們只需要讓其私有繼承自boost::noncopyable,

class student:private boost::noncopyable

{

......

}

當調用到派生類的拷貝構造函數或賦值函數進行復制時,不可避免的要調用基類對應的函數,因爲這些操作是private,這樣的操作會被編譯器拒絕。

需要注意,多重繼承有時會使空基類noncopyable優化失效,所以這不適合用於多重繼承的情形。



另外,如果只是不想要使用默認的拷貝構造函數或賦值函數,可以使用C++11提供的delete,

C++11則使用delete關鍵字顯式指示編譯器不生成函數的默認版本。比如:

class MyClass
{
  public:
    MyClass()=default;
    MyClass(const MyClass& )=delete;
  ......
}

當然,一旦函數被delete過了,那麼重載該函數也是非法的,該函數我們習慣上稱爲刪除函數。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章