第三章 類
第三節 inline,const,mutable, this, static
1. 在類定義中實現成員函數inline
-
類內的成員函數實現也叫做類內的成員函數定義
-
直接在類的定義中實現的函數直接被系統認爲是內聯函數(inline),但是能不能夠成功,取決於編譯器本身
#ifndef LESSION_PART_TWO_TIME_H
#define LESSION_PART_TWO_TIME_H
class Time {
private:
// 私有成員變量不能在外部直接用成員變量名使用
// 可以自己的成員函數調用
int Millisecond;//毫秒
void initMillTime(int mls);
public:
int Hour;
int Minute;
int Second;
// 成員函數
void initTime(int tmphour, int tmpmin, int tmpsec);
public:
//構造函數
Time(int tmphour, int tmpmin, int tmpsec = 22);
//不加參數
Time();
//單參數的構造函數
explicit Time(int tmphour);
//直接在類中定義的函數直接被系統認爲是內聯函數
void addHour(int temphour){
Hour += temphour;
}
};
#endif //LESSION_PART_TWO_TIME_H
2. 成員函數末尾的const
-
const 是一個常量的概念,在成員函數末尾增加const,不但要在成員函數聲明中增加const,也要在成員函數定義中增加const
-
作用: 告訴系統這個成員函數不會修改該對象裏任何成員的值,也就是說這個成員函數不會修改Time類中任何成員變量,這種函數也叫做常量成員函數
-
Time.h中
void addHour(int temphour) const;
- Time.cpp
//這種方式會報錯,因爲不允許修改對象中的成員變量,也就不能修改Hour的值
void Time::addHour(int temphour) const {
Hour = temphour+1;
}
一個const類對象的範例
- Time.h
//
// Created by felaim on 2020/5/26.
//
#ifndef LESSION_PART_TWO_TIME_H
#define LESSION_PART_TWO_TIME_H
class Time {
public:
int Hour;
int Minute;
int Second;
int Millisecond;//毫秒
// 成員函數
void initTime(int tmphour, int tmpmin, int tmpsec);
public:
//構造函數
Time(int tmphour, int tmpmin, int tmpsec = 22);
//不加參數
Time();
//單參數的構造函數
explicit Time(int tmphour);
void initMillTime(int mls);
void addHour(int temphour) const;
void noone() {}
void noonec() const {}
};
#endif //LESSION_PART_TWO_TIME_H
- Time.cpp
//
// Created by felaim on 2020/5/26.
//
#include "Time.h"
// 成員函數initTime的實現
// ::叫做作用域運算符,表示initTime屬於Time類
void Time::initTime(int tmphour, int tmpmin, int tmpsec) {
//成員函數中可以直接使用成員變量名
// 哪個對象調用的成員函數,這些成員變量就屬於對應的對象
Hour = tmphour;
Minute = tmpmin;
Second = tmpsec;
initMillTime(25);
}
void Time::initMillTime(int mls) {
Millisecond = mls; //成員函數訪問成員變量
}
Time::Time(int tmphour, int tmpmin, int tmpsec)
: Hour(tmphour), Minute(tmpmin), Second(tmpsec), Millisecond(0) {}
// 構造函數的實現
//Time::Time(int tmphour, int tmpmin, int tmpsec) {
// Hour = tmphour;
// Minute = tmpmin;
// Second = tmpsec;
//
// initMillTime(0);
//}
Time::Time() {
Hour = 12;
Minute = 59;
Second = 59;
}
Time::Time(int tmphour) {
Hour = tmphour;
Minute = 59;
Second = 59;
}
void Time::addHour(int temphour) const {
}
- main.cpp
#include <iostream>
#include "Time.h"
using namespace std;
int main() {
// 添加explict仍然可行
Time myTime{12, 12, 3};
cout << "myTime: " << myTime.Hour << ":" << myTime.Minute << ":" << myTime.Second << endl;
// 定義const對象
const Time cmyTime;
//報錯,不能調用修改對象的成員函數
//cmyTime.initMillTime(2);
// 也不能使用普通函數,因爲noone()沒有別被聲明成const
//cmyTime.noone();
//可以使用const 成員函數
cmyTime.noonec();
//initMillTime只能被非const對象調用
myTime.initMillTime(3);
cout << "myTime.Millisecond : " << myTime.Millisecond << endl;
myTime.noone();
//非const對象也可以調用const的成員函數
myTime.noonec();
return 0;
}
- const 成員函數不管是const對象還是非const對象都可以調用const成員函數,而非const成員函數,不能被const對象調用,只能被非const對象調用
3. mutable
-
mutable:不穩定,容易改變的意思,與const意思相反,mutable是爲了突破const的限制
-
用mutable來修飾一個成員變量,一個成員變量一旦被mutable修飾了,這個成員變量永遠處於可以被修改狀態,即便是在const結尾的成員函數中
-
一個簡單例子,先混個臉熟
//成員變量中添加public對象
mutable int testVal;
//成員函數中添加
void noonec() const {
testVal++;
}
// 主程序中進行測試
// 發現無論是不是const對象,都可以對mutable定義的testVal值進行修改
myTime.testVal=100;
cout << "myTime.testVal: " << myTime.testVal << endl;
cmyTime.testVal = 200;
cout << "cmyTime.testVal: " << cmyTime.testVal << endl;
4. 返回自身對象的引用,this
-
如何理解this?
調用成員函數的時候,編譯器負責把對象的地址(&mytime)傳遞給這個成員函數中的一個隱藏的this形參 -
在系統角度看來,任何對類成員的直接訪問,都被看作是通過this做隱式調用的
-
this指針只能在成員函數中使用,全局函數以及靜態函數都不能使用this指針
-
在普通成員函數中,this是指向非const對象的const指針,(類型爲Time,就是Time *const this),this只能指向當前這個對象,不能指向其他對象
-
在const成員函數中,this指針是一個指向const對象的const指針,(類型爲Time,就是const Time * const this)
代碼修改
- time.h
//
// Created by felaim on 2020/5/26.
//
#ifndef LESSION_PART_TWO_TIME_H
#define LESSION_PART_TWO_TIME_H
class Time {
public:
int Hour;
int Minute;
int Second;
int Millisecond;//毫秒
mutable int testVal;
// 成員函數
void initTime(int tmphour, int tmpmin, int tmpsec);
public:
// 返回對象自己
Time &addHour(int temphour);
Time &addMin(int Minute);
public:
//構造函數
Time(int tmphour, int tmpmin, int tmpsec = 22);
//不加參數
Time();
//單參數的構造函數
explicit Time(int tmphour);
void initMillTime(int mls);
void noone() {}
void noonec() const {
testVal++;
}
};
#endif //LESSION_PART_TWO_TIME_H
- Time.cpp(添加代碼)
// 返回對象自己
Time &Time::addHour(int temphour) {
Hour += temphour;//在系統看來等價與 this->Hour =+ temphour
return *this;
}
//編譯器內部操作, 添加了一個內部指針
//Time & Time::addHour(Time *this, int temphour) {}
//如果形參和成員變量名相同,需要添加this->來進行區分
Time &Time::addMin(int Minute) {
this->Minute += Minute;
return *this;
}
- main.cpp
#include <iostream>
#include "Time.h"
using namespace std;
int main() {
Time mytime;
cout << "mytime " << mytime.Hour << " : " << mytime.Minute << endl;
// 如果能返回自己,就可以進行連調
mytime.addHour(3).addMin(4);
cout << "mytime " << mytime.Hour << " : " << mytime.Minute << endl;
return 0;
}
5. static成員變量
-
屬於整個類的成員變量,這種成員變量就是static成員變量
-
特點: 不屬於某個對象,屬於整個類,一旦在某個對象中修改了這個成員變量的值,在其他對象中直接能夠看到修改的結果
-
這種成員變量只有一個副本,對於這種成員變量的引用,我們用的是類名::成員變量名
-
成員函數前面也可以加static,構成靜態成員函數,屬於整個類的成員函數,我們用類名::成員函數
如何定義靜態成員變量?
- 在某個.cpp源文件開頭定義這個靜態成員變量,這樣就能夠保證在調用任何函數之前這個靜態成員變量已經被成功初始化
(此時在分配內存)
代碼範例
- Time.h
//
// Created by felaim on 2020/5/26.
//
#ifndef LESSION_PART_TWO_TIME_H
#define LESSION_PART_TWO_TIME_H
class Time {
public:
int Hour;
int Minute;
int Second;
int Millisecond;//毫秒
mutable int testVal;
//聲明成員變量,還沒有被分配內存,所以不能在這裏初始化
// 靜態成員變量
static int mystatic;
public:
// 返回對象自己
Time &addHour(int temphour);
Time &addMin(int Minute);
public:
//構造函數
Time(int tmphour, int tmpmin, int tmpsec = 22);
//不加參數
Time();
//單參數的構造函數
explicit Time(int tmphour);
void initTime(int tmphour, int tmpmin, int tmpsec);
void initMillTime(int mls);
void noone() {}
void noonec() const {
testVal++;
}
// 靜態成員函數
static void mstafunc(int testValue);
};
#endif //LESSION_PART_TWO_TIME_H
- Time.cpp
//
// Created by felaim on 2020/5/26.
//
#include <iostream>
#include "Time.h"
// 靜態成員變量定義(分配內存),定義的時候不需要使用static
// 可以不給初值,系統默認給0
int Time::mystatic = 15;
void Time::initTime(int tmphour, int tmpmin, int tmpsec) {
Hour = tmphour;
Minute = tmpmin;
Second = tmpsec;
initMillTime(25);
}
void Time::initMillTime(int mls) {
Millisecond = mls; //成員函數訪問成員變量
}
Time::Time(int tmphour, int tmpmin, int tmpsec)
: Hour(tmphour), Minute(tmpmin), Second(tmpsec), Millisecond(0) {}
Time::Time() {
Hour = 0;
Minute = 0;
Second = 0;
}
Time::Time(int tmphour) {
Hour = tmphour;
Minute = 59;
Second = 59;
}
// 返回對象自己
Time &Time::addHour(int temphour) {
Hour += temphour;//在系統看來等價與 this->Hour =+ temphour
return *this;
}
//編譯器內部操作, 添加了一個內部指針
//Time & Time::addHour(Time *this, int temphour) {}
//如果形參和成員變量名相同,需要添加this->來進行區分
Time &Time::addMin(int Minute) {
this->Minute += Minute;
return *this;
}
//靜態成員函數中修改對象的成員變量
void Time::mstafunc(int testValue) {
mystatic = testValue;
}
- main.cpp
#include <iostream>
#include "Time.h"
using namespace std;
int main() {
Time mytime;
mytime.Minute = 15;
Time mytime2;
mytime2.Minute = 30;
cout << "mytime.Minute: " << mytime.Minute << endl;
cout << "mytime2.Minute: " << mytime2.Minute << endl;
cout << "Time::mystatic: " << Time::mystatic << endl;
cout << "mytime.mystatic: " << mytime.mystatic << endl;
mytime.mystatic = 88;
cout << "mytime2.mystatic: " << mytime2.mystatic << endl;
mytime2.mstafunc(199);
cout << "mytime.mystatic: " << mytime.mystatic << endl;
return 0;
}