const成員函數 :在成員函數後面加const,const修飾this指針所指向的對象,也就是保證調用這個const成員函數的對象在函數内不會被改變。
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{}
void Show1() const //const Date* this
{
cout << _year << "-" << _month << "-" << _day << endl;
}
void Show2()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
void F1()
{
Show1();
Show2();
}
void F2()const
{
Show1();
//Show2(); //出錯,const調用非const成員函數
}
private:
int _year;
int _month;
int _day;
};
1. const對象可以調用非const成員函數? 不可以>權限放大
2. 非const對象可以調用const成員函數嗎? 可以>權限縮小
3. const成員函數内可以調用其它的const成員函數非const成員函數嗎? 可以, 不可以
4. 非const成員函數内可以調用其它的const成員函數非const成員函數嗎? 可以 ,可以
類的靜态成員:聲明為static的類成員(成員資料或成員函數)稱為類的靜态成員
特征:
1.靜态成員為所有類對象所共享,不屬于某個具體的執行個體
2.類靜态成員即可用類名::靜态成員或者對象.靜态成員來通路
3.類靜态成員變量必須在類外定義,定義時不添加static關鍵字
4.類的靜态成員函數沒有預設的this指針,是以在它裡面不能使用任何非靜态成員
5.靜态成員和類的普通成員一樣,也有public、protected、private3種通路級别,也可以具有傳回值,const修飾符等參數
#include <iostream>
using namespace std;
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
:_year(year)
,_month(month)
,_day(day)
{
++_count;
}
Date(const Date& d)
:_year(d._year)
,_month(d._month)
,_day(d._day)
{
++_count;
}
void Show() const
{
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
GetCount();
}
// 沒有this指針
static int GetCount()
{
//_year = 10;
//Show();
return _count;
}
private:
int _year;
int _month;
int _day;
static size_t _count;
};
size_t Date::_count = 0;
int main()
{
Date d1(2018, 3, 26);
Date d2(2018, 3, 26);
cout<<d1.GetCount()<<endl;
cout<<d2.GetCount()<<endl;
cout<<Date::GetCount()<<endl; //通過類名通路靜态成員函數
return 0;
}
1. 靜态成員函數可以通路非靜态的成員嗎? 不能通路,靜态成員函數沒有this指針
2. 非靜态的成員函數可以通路靜态成員嗎? 可以通路,通過類域進行通路
再探拷貝構造函數的優化:
在一個步驟中,先構造了一個臨時對象,又用該臨時對象拷貝構造其他對象,會将二者合二為一
#include <iostream>
using namespace std;
class Date
{
public :
Date()
{
cout<<"Date()" <<endl;
}
Date(const Date& d)
{
cout<<"Date(const Date& d)" <<endl;
}
Date& operator=(const Date& d )
{
cout<<"Date& operator=(const Date& d)"<< endl;
return *this ;
}
~Date()
{
cout<<"~Date()" <<endl;
}
};
void fun1 (const Date& d)
{}
Date fun2()
{
//Date ret;
//return ret; //這裡發生拷貝構造臨時對象,ret被析構
return Date(); //直接傳回匿名對象,優化了拷貝構造
}
void fun3(Date d) //傳值,多調用一次拷貝構造,還要調析構
{
}
int main()
{
//情景1
//Date d1;
//fun1(d1); //d1已經存在,不會調用拷貝
//情景2 一次構造,一次析構
//fun3(Date()); //在一個步驟中,先構造了一個臨時對象,又用該臨時對象拷貝構造其他對象,會将二者合二為一,調用了構造,然後直接進行拷貝構造
//fun1(Date()); //結果相同,意義不同,這裡d是Date()的别名
Date d1 = fun2();//fun2中進行一次構造,一次拷貝構造
//Date d2; //構造
//d2 = fun2(); //構造、拷貝構造、指派運算符重載
//Date d3;
//Date();// 臨時對象,匿名對象,聲明周期隻在目前一行
//Date().Show(); // 臨時對象,匿名對象,聲明周期隻在目前一行,(使用場景:隻是調用一下某個對象的某個函數,調完以後不會再
// 用該對象,調用結束,立刻析構)
return 0;
}
#include <iostream>
using namespace std;
class AA
{
public:
AA()
{
cout << "AA()" << endl;
}
AA(const AA& A)
{
cout << "const AA(AA& A)" << endl;
}
AA& operator=(const AA& A)
{
cout << "AA& operator=(const &AA A)" << endl;
return *this ;
}
};
AA f(AA a)
{
return a;
}
void Test1() //二次拷貝構造,1次指派運算符的重載
{
AA a1;
a1 = f(a1);
}
void Test2() //二次拷貝構造,0次指派運算符的重載
{
AA a1;
AA a2 = f(a1);
}
void Test3() //三次拷貝構造,0次指派運算符的重載
{
AA a1;
AA a2 = f(f(a1));
}
int main()
{
printf("test1:\n");
Test1();
printf("test2:\n");
Test2();
printf("test3:\n");
Test3();
return 0;
}