模板篇
友元函數
關鍵字:friend
友元全局函數
友元成員函數
class Coordinate
{
friend void printXY(Coordinate &c);
};
友元,可以訪問對象中的 private
和protected
數據成員
雖然方便數據的直接訪問,但是也破壞了封裝性。不建議使用友元
友元類
class Circle;
class Coordinate{
friend Circle;
};
Circle 對象就可以任意訪問 Coordinate 對象的 數據成員 和 成員函數
關於友元的注意事項
- 友元關係不可傳遞
- 友元關係的單向性
- 友元聲明的形式及數量不受限制
友元只是封裝的補充,不建議
注:由於編譯器不同,友元類有兩種寫法。1、friend class 類名; 2、friend 類名;
static
靜態數據成員
靜態成員函數
靜態數據成員一般不在構造函數中實例化,一般單獨進行
class Tank{
public:
Tank() {s_iCount++;}
~Tank() {s_iCount--;}
static int s_iCount;
static int getCount();
};
int Tank::s_iCount = 0;
靜態數據和函數的訪問:(共享)
int main(void)
{
cout << Tank::getCount() << endl;
cout << Tank::s_iCount << endl;
Tank tank;
cout << tank.getCount() << endl;
cout << tank.s_iCount << endl;
return 0;
}
從this 指針談靜態成員函數
class Tank
{
public:
void fire();
static int getCount();
private:
string m_strCode;
static int s_iCount;
}
// 實際上,fire函數會隱式傳入一個 this 指針
void fire(Tank *this) {
this->m_strCode = "01";
s_iCount = 0;
}
// 靜態成員函數則不會 隱式 傳入一個 this 指針
static int getCount() {
m_strCode = "01"; // 報錯
return s_iCount;
}
注意事項
- 靜態數據成員必須單獨初始化
- 靜態成員函數不能調用非靜態成員函數和非靜態數據成員
- 靜態數據成員只有一份,且不依賴對象而存在,sizeof 不計算
- 靜態成員函數無法加 const,這與 this 指針的本質是相符合的
運算符重載
給原有的運算符賦予新的功能
如:給 + 號重載,使其能夠實現兩個字符串拼接
運算符重載的本質:函數重載
關鍵字:operator
一元運算符重載
-(負號)的重載:
-
友元函數重載
class Coordinate{ friend Coordinate& operator-(Coordinate &coor); }; // 定義 Coordinate& operator-(Coordinate &coor) { coor.m_iX = -coor.m_iX; coor.m_iY = -coor.m_iY; return *this; } // 使用 Coordinate coor1(3,5); -coor1; // operator-(coor1);
-
成員函數重載
class Coordinate{ public: Coordinate& operator-(); }; // 定義 Coordinate& Coordinate::operator-() { m_iX = -m_iX; m_iY = -m_iY; return *this; } // 使用 Coordinate coor1(3,5); -coor1; // coor1.operator-();
++符號的重載:
-
前置++符號重載
class Coordinate{ Coordinate& operator++(); // 前置++ }; // 定義 Coordinate& Coordinate::operator++(){ m_iX++; m_iY++; return *this; } // 使用 Coordinate coor1(3,5); ++coor1; // coor1.operator++();
-
後置++符號重載
Coordinate operator++(int); // 後置++ // 定義 Coordinate operator++(int){ Coordinate old(*this); m_iX++; m_iY++; return old; } // 使用 coor1++; // coor1.operator++(0);
二元運算符重載
+號運算符:
-
成員函數重載:
class Coordinate{ public: Coordinate operator+(const Coordinate &coor); }; // 定義 Coordinate operator+(const Coordinate &coor) { Coordinate temp; temp.m_iX = this->m_iX + coor.m_iX; temp.m_iY = this->m_iY + coor.m_iY; return temp; } // 使用 Coordinate coor1(3,5); Coordinate coor2(4,7); coor3 = coor1 + coor2; // coor1.operator+(coor2);
-
友元函數重載:
class Coordinate{ friend Coordinate operator+(const Coordinate &c1,const Coordinate &c2); }; // 定義 Coordinate operator+(const Coordinate &c1,const Coordinate &c2){ Coordinate temp; temp.m_iX = c1.m_iX + c2.m_iX; temp.m_iY = c1.m_iY + c2.m_iY; return temp; } // 使用 coor3 = coor1 + coor2; // operator+(coor1,coor2);
<< 運算符:
-
友元函數重載:
class Coordinate{ friend ostream& operator<<(ostream &out,const Coordinate &coor); }; // 定義 ostream &operator<<(ostream &out, const Coordinate &coor){ out << coor.m_iX << "," << coor.m_iY; return out; } // 使用 cout << coor; // operator<<(cout,coor);
-
**成員函數重載:**和this 的本質有關, << 運算符必須傳入 ostream,所以不能重載
[] 運算符
-
成員函數
class Coordinate{ public: int operator[](int index); }; // 定義 int Coordinate::operator [](int index) { if(index == 0) { return m_iX; } if(index == 1) { return m_iY; } } // 使用 Coordinate coor(3,5); cout << coor[0]; // coor.operator[](0); cout << coor[1]; // coor.operator[](1);
-
**友元函數重載:**和 this 本質有關, [] 運算符必須傳入 索引 值,所以不能重載
函數模板
關鍵字: template typename class
template <class T>
T max(T a,T b) {
return (a > b) ? a : b;
}
// 使用
int ival = max(100,99);
char cval = max<char>('A','B');
template<typename T>
void swap(T &a,T &b) {
T tmp = a;
a = b;
b = tmp;
}
// 使用
int x = 20,y = 30;
swap<int>(x,y);
**注意:**如果只有函數模板 而沒有對其進行調用,編譯後是不會產生代碼邏輯的,因爲類型不確定,並不知道產生什麼具體類型的函數
變量作爲模板參數
template<int size>
void display()
{
cout << size << endl;
}
display<10>();
多參數函數模板
template <typename T,typename C>
void display(T a,C b) {
cout << a << " " << b << endl;
}
// 使用
int a = 1024;
string str = "Hello world!";
display<int,string>(a,str);
typename 和 class 意義一樣,可以混用
函數模板與重載
template<typename T>
void display(T a);
template<typename T>
void display(T a,T b);
template<typename T,int size>
void display(T a);
類模板
template<class T>
class MyArray{
T *m_pArr;
};
template<class T>
void MyArray<T>::display(){
...
}
// 使用
MyArray<int> arr;
arr.display();
注意:模板代碼不能分離編譯
C++標準模板 STL
STL:Standard Template Lib
vector 向量
本質:對數組的封裝
動態增加或者減小數組長度
特點:讀取能在常數時間完成
vector 初始化:
vector<int> ivec1;
vector<int> ivec2(ivec1);
vector<string> svec1;
vector<string> svec2(ivec);
vector<int> ivec4(10,-1);
vector<string> svec(10, "hi!");
vector 常用函數:
vector 使用:
vector<int> vec;
vec.push_back(10);
vec.pop_back();
cout << vec.size() << endl;
for(int k = 0;k < vec.size();k++) {
cout << vec[k] << endl;
}
迭代器:iterator
vector vec;
vec.push_back("hello");
vector<string>::iterator citer = vec.begin();
for(;citer != vec.end();citer++) {
cout << *citer << endl;
}
list:鏈表
特點:數據插入速度快
map:映射
map<int,string> m;
pair<int,string> p1(10,"shanghai");
pair<int,string> p2(20,"beijing");
m.insert(p1);
m.insert(p2);
cout << m[10] << endl;
cout << m[20] << endl;
pair<int,string> p1("S","shanghai");
pair<int,string> p2("B","beijing");
m.insert(p1);
m.insert(p2);
cout << m["S"] << endl;
cout << m["B"] << endl;