第四周內(nèi)容比較的散,大綱如下
- Conversion Function
- non-explicit one argument constructor
- pointer-like classes
- Function-like classes
- namespace經(jīng)驗談
- class template
- Function Template
- Member Template
- specialization
- 模板偏特化
- 模板模板參數(shù)
- 關(guān)于C++標準庫
- 三個主題
- Reference
- 復(fù)合&繼承關(guān)系下的構(gòu)造和析構(gòu)
第四周的內(nèi)容也是相對零零散散,有虛函數(shù)指針vptr,虛函數(shù)表vtbl的,有this指針,有動態(tài)綁定Dynamic Binding。后邊還講到了成員函數(shù)。能寫多少寫多少吧。
- Conversion Function
Operator 類型名(){轉(zhuǎn)換語句}
比如這個例子:
#include<iostream>
using namespace std;
class Fraction
{
public:
Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) { }
operator double( ) const
{
cout<<"operator double( ) is called!!!"<<endl;
return (double)(m_numerator / m_denominator);
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
int main( )
{
Fraction f(3, 5);
double d = 4+f; //調(diào)用operator double( ) 將f 轉(zhuǎn)換為0.6.
return 0;
}
轉(zhuǎn)換函數(shù)在函數(shù)名前面不能指定函數(shù)類型,函數(shù)也沒有參數(shù),至于是否要加const,根據(jù)轉(zhuǎn)換后的結(jié)果來判定,一般都會加上const。在使用過程中,不必顯示地調(diào)用類型轉(zhuǎn)換函數(shù),它往往是自動被調(diào)用的,即隱式調(diào)用。
23轉(zhuǎn)換構(gòu)造函數(shù):一個參數(shù)的構(gòu)造函數(shù)(或者除了第一個參數(shù)外其余參數(shù)都有默認值的多參構(gòu)造函數(shù))。
它有兩個作用:一是構(gòu)造器,二是默認且隱式的類型轉(zhuǎn)換操作符。
- 關(guān)鍵字explicit:
Explicit用于防止隱式轉(zhuǎn)換的,普通的構(gòu)造函數(shù)能過被隱式調(diào)用,而explicit構(gòu)造函數(shù)只能被顯示調(diào)用。
non-explicit-one-argument ctor 可隱式轉(zhuǎn)換單一形參構(gòu)造函數(shù)形如:
#include<iostream>
using namespace std;
class Fraction
{
public:
Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den)
{
cout<<"non-explicit ctor is called!!!"<<endl;
}
Fraction operator + (const Fraction &f)
{
cout<<"operator +(...) is called!!!"<<endl;
return Fraction(this->m_numerator+f.m_numerator, this->m_denominator+f.m_denominator);
}
int getNumerator() const {return m_numerator;}
int getDenominator() const {return m_denominator;}
private:
int m_numerator; //分子
int m_denominator; //分母
};
ostream& operator<<(ostream &os, const Fraction &f)//重載<<運算符
{
return os<<"分子: "<<f.getNumerator()<<"分母: "<<f.getDenominator();
}
int main( )
{
Fraction f(3, 5); //調(diào)用non-explicit ctor
Fraction d2 = f+4; //調(diào)用non-explicit ctor將4轉(zhuǎn)為 Fraction(4,1)
//然后調(diào)用operator +
cout<<d2<<endl; //因為引用傳遞,所以會再調(diào)用一次non-explicit ctor
return 0;
}
- shared_ptr是一種智能指針(smart point),它會記錄有多少個shared_ptr共享一個對象。當最后一個指向?qū)ο蟮闹羔槺讳N毀,這個對象就會被自動刪除。
**shared_ptr<int> sp(new int(10)); //一個指向整數(shù)的shared_ptr
assert(sp.unique()); //現(xiàn)在shared_ptr是指針的唯一持有者
shared_ptr<int> sp2 = sp; //第二個shared_ptr,拷貝構(gòu)造函數(shù)
assert(sp == sp2 && sp.use_count() == 2); //兩個shared_ptr相等,指向同一個對象,引用計數(shù)為2
*sp2 = 100; //使用解引用操作符修改被指對象
assert(*sp == 100); //另一個shared_ptr也同時被修改
sp.reset(); //停止shared_ptr的使用
assert(!sp); //sp不再持有任何指針(空指針)
**
網(wǎng)上的例子。
- 迭代器(iterator)
迭代器提供對一個容器中的對象的訪問方法,并定義了容器中對象的范圍。迭代器就如同一個指針。
- typename
這周課侯老師講了在泛型編程中typename和class具體有無區(qū)別。侯老師也講了,在模板聲明里是完全沒用區(qū)別的。侯老師也提到了在模板里面的使用是有些微的區(qū)別的。但是限于篇幅與時間的限制,侯老師并沒有深入討論,所以在本筆記中,我們會討論typename與class的區(qū)別。
比如我們有一個模板函數(shù),該函數(shù)可以打印容器內(nèi)的所有元素。如下圖所示,即使沒有typename,函數(shù)也能運行。
可是,如果我們寫一個自己的容器類,不但有const_iterator這一迭代器類型,還有一個靜態(tài)變量也叫const_iterator。這時候編譯器就會會出現(xiàn)解析錯誤了。因為我們知道,靜變量可以通過使用類名::變量名調(diào)用的。所以T::const_iterator不但是一個類型名還是一個變量名,這時候就要加入typename了。
- 范圍for語句
C++11新引入了一種更簡單的for語句,用于遍歷容器或其它序列的所有元素。
語法結(jié)構(gòu):
for(declaration : expression){
……
}
expression為要遍歷的容器
declaration為變量類型,用于存放容器中的元素,若是不清楚容器中的元素類型,可以使用auto類型說明符。
例如:
vector<int> v={0,1,2,3,4,5,6,7,8,9};
for(auto r:v)
{
cout<<r<<endl;
}
在上面的代碼中提到了auto,它是類型說明符。
在編程時,常常需要把表達是的值賦值給變量,這就要求在聲明變量的時候清楚地知道表達式的類型,然而,往往做不到這一點,所以引入了auto類型說明符,它讓編譯器通過初始值來推算變量的類型。所以,auto定義的變量一定要有初始值。
6.[GeekBand][C++面向?qū)ο蟾呒壘幊?下)]第四周作業(yè)
作業(yè)解答在這里