Essential C++Chap4(基于对象)

1.

As with the definition of a nonmember inline function, an inline member function 

should be placed in a header file. The class definition and the inline member functions are 

typically placed in a header file given the name of the class. 

inline函数的定义要放到头文件里。

2.

We identify a constructor by giving it the same name as the class.The syntactic rules are that the 

constructor must not specify a return type nor return a value.

构造函数无返回值哦。

3.

Surprisingly, the following does not define a Triangular class object: 

Triangular t5(); // not what it seems :-)  

Rather, this defines t5 to be a function with an empty parameter list and returning a Triangular 

object. Obviously, this is a weird interpretation. Why is it interpreted this way? It's because C++ 

once needed to be compatible with the C language, and in C the parentheses following t5 in this 

case identify it as a function. The correct declaration of t5 is the same as t, shown earlier: 

Triangular t5; // ok 

Triangular t5();不会调用默认构造函数生成一个对象,而是定义了一个函数!Triangular t5;才定义了一个对象。

4.

默认形参有时可以取代函数重载,提供参数初始化表也是构造函数经常使用的特性。

5.

类中使用了动态分配的内存时,别忘了在析构函数~中delete掉。

6.

When we design a class, we must ask ourselves whether the default memberwise behavior is 

adequate for the class. If it is, we need not provide an explicit copy constructor. If it is not, we 

must define an explicit instance and within it implement the correct initialization semantics. 

If our class requires a copy constructor, it also requires a copy assignment operator.

当类中有动态分配的内存时,就要考虑深拷贝和浅拷贝的问题,要提供默认构造函数,并且重载=操作符。

7.

The const modifier follows the parameter list of the function. A const member function 

defined outside the class body must specify the const modifier in both its declaration and 

definition. For example, 

int Triangular::elem(int pos) const  

    { return _elems[pos-1]; }

类外定义的const函数,必须在声明和定义处都加const。

8.

In the following class, the val() member function does not directly modify the _val data 

member, but it does return a non-const reference to _val. Can val() still be declared as 

const? 

class val_class {  

public:  

   val_class(const BigClass &v)  

       : _val(v){}  

   // is this ok?  

   BigClass& val() const { return _val; }  

private:  

   BigClass _val;  

};  

No. Returning a non-const reference to _val in effect opens it to modification in the general 

program. Because a member function can be overloaded based on its constness, one solution to 

this problem is to provide two definitions — a const and a non-const version — such as the following: 

class val_class {  

public:  

   const BigClass& val() const { return _val; }  

   BigClass& val(){ return _val; }  

   // ...  

};  For a non-const class object, the non-const instance of val() is invoked. For a const class 

object, the const instance is invoked.

const成员函数不能返回非常引用,但是可以通过一个函数是否有const属性来进行重载。const对象会自动调用const函数。

9.

The mutable keyword provides us with a way of making just such a claim. By identifying _next as mutable, we are 

saying that changes to it do not violate the const-ness of our class object. 

class Triangular {  

public:  

   bool next(int &val) const;  

   void next_reset() const { _next = _beg_pos - 1; }  

   // ...  

private: 

 mutable int _next,  

   int _beg_pos;  

   int _length;  

};  

next() and next_reset() can now modify _next and still be declared as const member 

functions, allowing our alternative implementation of sum().

有时候常对象调用的函数里可能修改对象中的某个非关键变量,此时必须把相应的函数声明成const类型的,怎么办?用mutable修饰的

变量可以在const函数中被改变!

10.

tr1.copy(tr2);  is internally transformed into 

// internal code transformation:  

// tr1 becomes the class object addressed by the this pointer  

copy(&tr1, tr2);  

Inside a class member function, the this pointer provides access to the class object through 

which the member function is invoked. To return tr1 from within copy(), we simply 

dereference the this pointer as follows: 

// returns the class object addressed by the this pointer  

return *this;

每个成员函数都默认带了个this指针参数。

11.

A const static int data member, such as buf_size, next, is the one instance in which a 

class member can be explicitly initialized within its declaration

static成员要在类外定义,并且不能再声明的时候初始化,const类型的staic变量可以在声明时初始化。

12.

When defined outside the class body, the static keyword is not repeated (this is also true of static data members)

在类中声明时用了static,在定义是就不必再用static了。这跟const修饰的函数可不同,后者必须要在声明和定义处都写const。

13.

The parameter list of a nonmember operator always defines one more parameter than its member 

operator counterpart. In a member operator, the this pointer implicitly represents the left operand. 

这是对于双目运算符而言。

14.

We must provide a prefix (++trian) and postfix (trian++) instance of the increment operator. 

The prefix instance is defined with an empty parameter list: 

inline int& Triangular_iterator::  

operator++()  

{   // prefix instance  

    ++_index;  

    check_integrity();  

    return Triangular::_elems[_index];  

}  

Ordinarily, the postfix instance would also be defined with an empty parameter list. However, 

each overloaded operator must have a unique parameter list. The language solution is to require 

that we define the postfix instance with a single integer parameter: 

inline int Triangular_iterator::  

operator++(int)  

{  

    // postfix instance  

    check_integrity();  

    return Triangular::_elems[_index++];  

}  

Both the prefix and the postfix instance of the increment (and decrement) operator can be applied 

directly to an object of the class: 

++it; // prefix  

it++; // postfix  

Where is the single integer argument for the postfix instance? The compiler generates that for us 

automatically to force the postfix instance of the operator to be called. Happily, the user does not 

need to bother about it.  

注意这个比较容易让人产生疑惑,其实++ --运算符的重载是一个特例,记住就好了。

15.

类中typedef的声明,被称为嵌套类型,应该用 类名:嵌套名 的格式使用。

16.

The Matrix class requires both a copy constructor and a copy assignment operator. Here is how we 

might define the Matrix copy assignment operator: 

Matrix& Matrix::  

operator=(const Matrix &rhs)  

{  

   if (this != &rhs)  

   {  

        _row = rhs._row; _col = rhs._col;  

        int elem_cnt = _row * _col;  

        delete [] _pmat;  

        _pmat = new double[elem_cnt];  

        for (int ix = 0; ix < elem_cnt; ++ix]  

              _pmat[ix] = rhs._pmat[ix];  

   }  

   return *this;  

};  

If the class designer provides an explicit instance of the copy assignment operator, that instance is 

used in place of default memberwise initialization. The source code of the user need not change, 

although it must be recompiled.

赋值运算符重载的小例子,注意返回值。

17.

When the compiler encounters what appears to be a function call, such as 

lt(ival);  

lt can be the name of a function, a pointer to function, or an object of a class that has provided an 

instance of the function call operator. If lt is a class object, the compiler internally transforms the 

statement as follows: 

lt.operator()(ival); // internal transformation

18.

static vector<vector<int> > seq;一定要注意那个空格。

typedef void (num_sequence::*PtrType)(int);  

PtrType pm = 0; 

PtrType pm = &num_sequence::fibonacci;

pm = &num_sequence::triangular;

指向类成员函数的指针声明,定义,赋值

19.

Unlike a pointer to function, a pointer to member function must be invoked through an object of 

the member function's class. The object becomes the this pointer of the member function that is 

invoked. 

For example, suppose we are given the following definitions: 

num_sequence ns;  

num_sequence *pns = &ns;  

PtrType pm = &num_sequence::fibonacci;  

To invoke pmf through ns, we write 

// equivalent to ns.fibonacci(pos)  

(ns.*pm)(pos)  

The .* pair of symbols is the pointer to member selection operator for class objects. The 

parentheses are necessary for it to be evaluated correctly. The pointer to member selection 

operator for a pointer to class operator is the ->* pair of symbols: 

// equivalent to pns->fibonacci(pos)  

(pns->*pm)(pos)  

原文地址:https://www.cnblogs.com/liujiahi/p/2201654.html