构造函数的初始化
class A{
private:
int i = 10;
int j = 20;
int k = t(i);
public:
A() : k(12){
cout << "i = " << i << " j = " << j << " k = " << k << endl;
}
int t(int i){
cout << "func t() " << endl;
return (i + 13);
}
};
int main(){
A a;
return 0;
}
// out
// i = 10 j = 20 k = 12
class A{
private:
int i = 10;
int j = 20;
int k = t(i);
public:
A() : i(12){
cout << "i = " << i << " j = " << j << " k = " << k << endl;
}
int t(int i){
cout << "func t() " << endl;
return (i + 13);
}
};
// out
// func t()
// i = 12 j = 20 k = 25
构造函数的初始化列表的执行先于构造函数,同样初始化列表的优先级先于定义初始化。
class B{
private:
int i;
public:
B(int j): i(j){
cout << "B() " << j << endl;
}
};
class A{
private:
B b1, b2;
public:
A() : b2(1), b1(2){
}
int t(int i){
cout << "func t() " << endl;
return (i + 13);
}
};
// out
// B() 2
// B() 1
构造函数的执行顺序是成员变量的书写顺序而不是初始化列表的书写顺序。
class A{
private:
int i;
string s;
public:
A(int i) : s("hello"){}
A(){
s = "hello";
}
相比之下,第二种的效率更低,原因是程序在执行的时候首先需要构造出一个空白的string类,之后再把它赋值为“hello”,而前一种则直接调用string类的构造器完成构造。
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
class A{
private:
string s;
public:
A() : s("hello"){}
A(int i){
s = "hello";
}
};
int main(){
clock_t begin1 = clock();
for(int i = 0; i < 100; i++){
A a1;
}
clock_t end1 = clock();
clock_t begin2 = clock();
for(int i = 0; i < 100; i++){
A a2(1);
}
clock_t end2 = clock();
cout << "first: " << end1 - begin1 << "ms" << endl;
cout << "second: " << end2 - begin2 << "ms" << endl;
return 0;
}
// out
// first: 16ms
// second: 7ms
Overloading
函数重载的条件是参数不一样,注意返回值不同无法区分两个函数。
对于函数的默认参数值,如果在“.h”文件中已经声明,那么在“.cpp”文件中不能再次声明。其实默认参数值并非函数本身实现的,而是编译器在编译程序的时候实现的。
inline
内联函数是declaration不是definition,因此inline函数必须写在头文件里。
一般而言,较短的函数适合改编为内联函数,较长的函数或者循环较多的函数不适合设计成内联函数。其实,一些编译器可以自动识别函数是否值得改写为内联函数。
const
char * const q = "abc"; // Pointer q is a const.
q = 'c'; // OK
q++; // ERROR
const char * q = "abc"; // Contect that q points to is a const.
q = 'c'; // ERROR
const char * q = "abc";
// It means that we couldn't change "abc" via q, while "abc" is changable.
const与成员函数
在代码和头文件里都需要声明const成员函数
class Date{
private:
int day;
public:
void set_day();
const int get_day();
}
void Date::set_day(int d){
day = d;
}
int Date::get_day() const{
day++ // Valid to change memble value.
set_day(1) // Valid to call a non-const memble function
return day;
}
注意const和非const的函数是可以overload的,因为在c++语法糖中每一个成员函数都有一个隐藏的指针参数,const是修饰该参数的。
如果一个类有一个const的成员变量,那么需要在构造函数的初始化列表里或者定义初始化中完成初始化。
static
一个静态的成员变量需要在类里面声明是static(.h文件)在代码文件里再加一个定义(不能在此加static)(.cpp文件)。