c++ primer笔记2

1、构造函数初始化列表

Conceptually, we can think of a constructor as executing in two phases: (1) the initialization phase and (2) a general computation phase. The computation phase consists of all the statements within the body of the constructor. Data members of class type are always initialized in the initialization phase, regardless of whether the member is initialized explicitly in the constructor initializer list. Initialization happens before the computation phase begins.

class A
{
public:
// 调用string的复制构造函数
A(const string &str) : data(str)

// 第一阶段调用string的默认构造函数,第二阶段调用string的赋值操作符
A(const string &str)
{

data = str;
}


private:

string data;
};

Some members must be initialized in the constructor initializer. Members of a class type that do not have a default constructor and members that are const or reference types must be initialized in the constructor initializer regardless of type.
The order in which members are initialized is the order in which the members are defined, not the order in which the initializer list provides.

2、隐式类型转换函数

A constructor that can be called with a single argument defines an implicit conversion from the parameter type to the class type.Ordinarily, single-parameter constructors should be explicit unless there is an obvious reason to want to define an implicit conversion. Making constructors explicit may avoid mistakes, and a user can explicitly construct an object when a conversion is useful.

3、友元的声明和范围

class Screen 
{
// Window_Mgrmust be defined before class Screen
friend Window_Mgr& Window_Mgr::relocate(int, int, Screen&);
};

Interdependencies among friend declarations and the definitions of the friends can require some care in order to structure the classes correctly. In the previous example, class Window_Mgr must have been defined. Otherwise, class Screen could not name a Window_Mgr function as a friend. However, the relocate function itself can’t be defined until class Screen has been defined. After all, it was made a friend in order to access the members of class Screen.
A friend declaration introduces the named class or nonmember function into the surrounding scope. Moreover, a friend function
may be defined inside the class. The scope of the function is exported to the scope enclosing the class definition.

class X 
{

friend class Y;
friend void f() { /* ok to define friend function in the class body */ }
};
class Z
{

Y *ymem; // ok: declaration for class Y introduced by friend in X
void g() { return ::f(); } // ok: declaration of f introduced by X
};

4、静态成员

Because a static member is not part of any object, static member functions may not be declared as const . After all, declaring a member function as const is a promise not to modify the object of which the function is a member. Finally, static member functions may also not be declared as virtual.
static data members must be defined (exactly once) outside the class body.

class Account 
{
public:
void applyint() { amount += amount * interestRate; }
static double rate() { return interestRate; }
static void rate(double); // sets a new rate
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();
static void test();
};

double Account::interestRate = initRate();
void Account::test()
{
initRate();
}

Like other member definitions, the definition of a static member is in class scope once the member name is seen. 静态数据成员interestRate的定义和静态函数test的定义都是在class类作用域内,所以它们都可以使用类作用域内的成员,哪怕它们是private。As a result, we can use the static member function named initRate directly without qualification as the initializer for interestRate. Note that even though initRate is private, we can use this function to initialize interestRate. The definition of interestRate, like any other member definition, is in the scope of the class and hence has access to the private members of the class. The static keyword, however, is used only on the declaration inside the class body. Definitions are not labeled static.

class Account 
{
public:
static double rate() { return interestRate; }
static void rate(double); // sets a new rate
private:
static const int period = 30; // interest posted every 30 days
double daily_tbl[period]; // ok: period is constant expression
};

A const static data member of integral type can be initialized within the class body.When a const static data member is initialized in the class body, the data member must still be defined outside the class definition.
const int Account::period;

5、静态成员不是类对象的一部分

Because static data members are not part of any object, they can be used in ways that would be illegal for non static data members.
As an example, the type of a static data member can be the class type of which it is a member. A non static data member is restricted to being declared as a pointer or a reference to an object of its class:

class Bar 
{

public:
// ...
private:
static Bar mem1; // ok
Bar *mem2; // ok
Bar mem3; // error
};

a static data member can be used as a default argument:

class Screen 
{
public:
Screen& clear(char = bkground);
private:
static const char bkground = '#';
};