標籤:
<Item 5> Know what functions C++ silently writes and calls
1、If you don‘t declare them yourself, compilers will declare their own versions of a copy constructor, a copy assignment operator, and a destructor. Furthermore, if you declare no constructors at all, compilers will also declare a default constructor for you. All these functions will be both public and inline (see Item 30).These functions are generated only if they are needed, but it doesn‘t take much to need them. The following code will cause each function to be generated:
Empty e1; // default constructor;// destructorEmpty e2(e1); // copy constructore2 = e1; // copy assignment operator
2、編譯器預設產生的函數都回做些什麼呢?Well, the default constructor and the destructor primarily give compilers a place to put "behind the scenes" code such as invocation of constructors and destructors of base classes and non-static data members.Note that the generated destructor is non-virtual (see Item7) unless it‘s for a class inheriting from a base class that itself declares a virtual destructor (in which case the function‘s virtualness comes from the base class). As for the copy constructor and the copy assignment operator, the compiler-generated versions simply copy each non-static data member of the source object over to the target object.
3、compiler-generated copy assignment operators behave as I‘ve described only when the resulting code is both legal and has a reasonable chance of making sense. If either of these tests fails, compilers will refuse to generate an operator= for your class.
template<class T>class NamedObject {public:// this ctor no longer takes a const name, because nameValue// is now a reference-to-non-const string. The char* constructor// is gone, because we must have a string to refer to.NamedObject(std::string& name, const T& value);... // as above, assume no// operator= is declaredprivate:std::string& nameValue; // this is now a referenceconst T objectValue; // this is now const};std::string newDog("Persephone");std::string oldDog("Satch");NamedObject<int> p(newDog, 2); // when I originally wrote this, our// dog Persephone was about to// have her second birthdayNamedObject<int> s(oldDog, 36); // the family dog Satch (from my// childhood) would be 36 if she// were still alivep = s; // what should happen to// the data members in p?
C++ doesn‘t provide a way to make a reference refer to a different object.Faced with this conundrum, C++ refuses to compile the code. If you want to support assignment in a class containing a reference member, you must define the copy assignment operator yourself. Compilers behave similarly for classes containing const members. Finally, compilers reject implicit copy assignment operators in derived classes that inherit from base classes declaring the copy assignment operator private.(需要copy基類部分,但是無權訪問基類copy函數,因此不會產生)
4、Things to Remember
Compilers may implicitly generate a class‘s default constructor, copy constructor, copy assignment operator, and destructor.
<Item 6> Explicitly disallow the use of compiler-generated functions you do not want
5、Instead, declare the copy constructor and the copy assignment operator private. By declaring a member function explicitly, you prevent compilers from generating their own version, and by making the function private, you keep people from calling it.
6、如果進一步不想讓友元函數和成員函數調用:This trick — declaring member functions private and deliberately not implementing them — is so well established, it‘s used to prevent copying in several classes in C++‘s iostreams library. Take a look, for example, at the definitions of ios_base, basic_ios, and sentry in your standard library implementation. You‘ll find that in each case, both the copy constructor and the copy assignment operator are declared private and are not defined.(common convention:聲明時只使用參數類型省略參數名字),這種類型是link-time error。
7、It‘s possible to move the link-time error up to compile time (always a good thing — earlier error detection is better than later) by declaring the copy constructor and copy assignment operator private not in HomeForSale itself, but in a base class specifically designed to prevent copying. The base class is simplicity itself:
class Uncopyable {protected: // allow constructionUncopyable() {} // and destruction of~Uncopyable() {} // derived objects...private:Uncopyable(const Uncopyable&); //...but prevent copyingUncopyable& operator=(const Uncopyable&);};class HomeForSale: private Uncopyable { // class no longer... // declares copy ctor or}; // copy assign. operator
這樣HomeForSale就不再能複製和賦值
8、std::vector實現的前提是其中的對象可以複製,大多數情況下,我們應該在其中存放對象的引用而不是值。
9、The implementation and use of Uncopyable include some subtleties, such as the fact that inheritance from Uncopyable needn‘t be public (see Items 32 and 39) and that Uncopyable ‘s destructor need not be virtual (see Item 7). Because Uncopyable contains no data, it‘s eligible for the empty base class optimization described in Item 39, but because it‘s a base class, use of this technique could lead to multiple inheritance (see Item 40). Multiple inheritance, in turn, can sometimes disable the empty base class optimization (again, see Item 39). In general, you can ignore these subtleties and just use Uncopyable as shown, because it works precisely as advertised. You can also use the version available at Boost (see Item 55). That class is named noncopyable. It‘s a fine class, I just find the name a bit un-, er, non natural.
10、Things to Remember
? To disallow functionality automatically provided by compilers, declare the corresponding member functions private and give no implementations. Using a base class like Uncopyable is one way to do this.
<Item 7> Declare destructors virtual in polymorphic base classes
11、C++ specifies that when a derived class object is deleted through a pointer to a base class with a non-virtual destructor, results are undefined. What typically happens at runtime is that the derived part of the object is never destroyed.Eliminating the problem is simple: give the base class a virtual destructor. Then deleting a derived class object will do exactly what you want. It will destroy the entire object, including all its derived class parts:(即使使用多台,在基類中定義虛解構函式也不一定是真理,例如由於ABI/(Application Binary Interface 應用二進位介面)的緣故,COM就不再介面定義中使用虛解構函式,也不使用new/delete)。Any class with virtual functions should almost certainly have a virtual destructor.
15、If a class does not contain virtual functions, that often indicates it is not meant to be used as a base class. When a class is not intended to be a base class, making the destructor virtual is usually a bad idea.
<Effective C++>讀書筆記--Ctors、Dtors and Assignment Operators