最容易想到的是將拷貝構造函數與賦值函數聲明爲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過了,那麼重載該函數也是非法的,該函數我們習慣上稱爲刪除函數。