C++ 面向?qū)ο蟾呒?jí)編程 (下) week 1 (Boolan)

本課程是上一門視頻課程"面向?qū)ο蟪绦蛟O(shè)計(jì)"(即: C++面向?qū)ο蟾呒?jí)編程(上))的續(xù)集, 將繼續(xù)探討一些未及討論的主題:

  • operator type() const
  • explicit complex(...): initialization list { }
  • pointer-like object
  • function-like object
  • namespace
  • template specialization
  • Standard library
  • variadic template (C++ 11)
  • auto (C++ 11)
  • range-base for loop (C++ 11)

課程目標(biāo)

  • 在先前基礎(chǔ)課程所培養(yǎng)的正規(guī), 大器的編程素養(yǎng)上, 繼續(xù)探討更多技術(shù).
  • 泛型編程(Generic Programming)和面向?qū)ο缶幊?Object-Oriented Programming)雖然分屬不同的思維, 但它們正是C++的技術(shù)主線, 所以本課程也討論template(模板).
  • 深入探索面向?qū)ο笾^承關(guān)系(inheritance)所形成的對象模型(Object Model), 包括隱藏于底層的this指針, vptr(虛指針), vtbl(虛表), virutual mechanism(虛機(jī)制), 以及虛函數(shù)(virtual functions)造成的polymorphism(多態(tài))效果.

推薦書目

  1. C++ Primer (5th Edition) by Stanley B. Lippman
  2. The C++ Programming Language (4th Edition) by Bjarne Stroustrup
  3. Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition) by Scott Meyers
  4. Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14 by Scott Meyers
  5. The C++ Standard Library - A Tutorial and Reference (2nd Edition) by Nicolai M. Josuttis
  6. STL源碼剖析 by 侯捷

點(diǎn)評(píng): 選擇一本好的C++書籍(1和2兩本書皆可), 然后以及盡量多的完成書籍的習(xí)題,可以幫助完成C++語法的學(xué)習(xí); 熟悉C++的語法后,通過3和4學(xué)習(xí)如何正確高效地使用C++/C++11/C++14; 如果對STL的一些實(shí)現(xiàn)有興趣嗦哆,可參考書目5和6.

conversion operator, 轉(zhuǎn)換函數(shù)

class Fraction {
 public:
  Fraction(int num, int den = 1) 
   : m_numerator(num), m_denominator(den) { }
  operator double() const  {
    return (double) m_numerator / m_denominator;
  }
 private:
  int m_numerator;    // 分子
  int m_denominator;  // 分母
};
Fraction f(3, 5);
double d = 4 + f;  // 調(diào)用operator double()將f轉(zhuǎn)為0.6

摘自C++ Primer:

A conversion operator is a special kind of member function that converts a value of a class type to a value of some other type. A conversion function typically has the general form
operator type() const;
where type represents a type. Conversion operators can be defined for any type (other than void) that can be a function return type. Conversions to an array or a function type are not permitted. Conversions to pointer types—both data and function pointers—and to reference types are allowed.
Conversion operators have no explicitly stated return type and no parameters, and they must be defined as member functions. Conversion operations ordinarily should not change the object they are converting. As a result, conversion operators usually should be defined as const members.

non-explicite-one-argument ctor

class Fraction {
 public:
  Fraction(int num, int den = 1)
   : m_numerator(num), m_denominator(den) { }
  Fraction operator+(const Fraction &f) {
    return Fraction(......);
  }
 private:
  int m_numerator;
  int m_denominator; 
};
Fraction f(3, 5);
Fraction d2 = f + 4;  // 調(diào)用non-explicit ctor將4轉(zhuǎn)為Fraction(4,1)
                      // 然后調(diào)用operator+

Note (摘自C++ Primer):

A constructor that can be called with a single argument defines an implicit conversion from the constructor’s parameter type to the class type.

Why explicit?

class Fraction {
 public:
  Fraction(int num, int den = 1)
   : m_numerator(num), m_denominator(den) { }
  operator double() const  {
    return (double) m_numerator / m_denominator;
  }
  Fraction operator+(const Fraction &f) {
    return Fraction(......);
  }
 private:
  int m_numerator;
  int m_denominator; 
};
Fraction f(3, 5);
Fraction d2 = f + 4;  // [Error] ambiguous

點(diǎn)評(píng): 在這個(gè)例子中, conversion function負(fù)責(zé)將Fraction轉(zhuǎn)化為double, 而non-explicit-one-argument ctor負(fù)責(zé)將double轉(zhuǎn)化為Fraction. 然而當(dāng)conversion function和non-explicit-one-argument ctor同時(shí)存在時(shí), 程序出現(xiàn)了二義性問題. 對于編譯器而言, Fraction d2 = f + 4可以理解成4轉(zhuǎn)為Fraction然后調(diào)用operator+,同時(shí)也可以理解成f轉(zhuǎn)成double, 和4做加法后再轉(zhuǎn)為Fraction, 所以程序是無法編譯通過的.

新的explicit-one-argument ctor:

  explicit Fraction(int num, int den = 1)
   : m_numerator(num), m_denominator(den) { }

關(guān)于explicit(摘自C++ Primer):

We can prevent the use of a constructor in a context that requires an implicit conversion by declaring the constructor as explicit. The explicit keyword is meaningful only on constructors that can be called with a single argument. Constructors that require more arguments are not used to perform an implicit conversion, so there is no need to designate such constructors as explicit. The explicit keyword is used only on the constructor declaration inside the class. It is not repeated on a definition made outside the class body.

pointer-like classes, 關(guān)于智能指針

template <class T>
class shared_ptr {
 public:
  T& operator*() const { return *px; }
  T* operator->() const { return px; }
  shared_ptr(T* p): px(p) { }
 private:
  T *px;
  long *pn;
};

關(guān)于pointer-like class和value-like class(摘自C++ Primer):

Classes that behave like values have their own state. When we copy a valuelike object, the copy and the original are independent of each other. Changes made to the copy have no effect on the original, and vice versa.
Classes that act like pointers share state. When we copy objects of such classes, the copy and the original use the same underlying data. Changes made to the copy also change the original, and vice versa.
Of the library classes we’ve used, the library containers and string class have valuelike behavior. Not surprisingly, the shared_ptr class provides pointerlike behavior, as does our StrBlob class (§ 12.1.1, p. 456). The IO types and unique_ptr do not allow copying or assignment, so they provide neither valuelike nor pointerlike behavior.

function-like classes, 所謂仿函數(shù)

template <class T>
struct identity {
  const T& operator() (const T &x) const { return x; }
};

template <class Pair>
struct select1st {
  const typename Pair::first_type&
  operator() (const Pair &x) const
  { return x.first; }
};

template <class Pair>
struct select2st {
  const typename Pair::second_type&
  operator() (const Pair &x) const
  { return x.second; }
};

Function-like class/functor (摘自Numberical Recipes):

A functor is simply an object in which the operator () has been overloaded to play the role of returning a function value.

namespace

關(guān)于namespace的定義(摘自C++ Primer):

A namespace definition begins with the keyword namespace followed by the namespace name. Following the namespace name is a sequence of declarations and definitions delimited by curly braces. Any declaration that can appear at global scope can be put into a namespace: classes, variables (with their initializations), functions (with their definitions), templates, and other namespaces. As with any name, a namespace name must be unique within the scope in which the namespace is defined. Namespaces may be defined at global scope or inside another namespace. They may not be defined inside a function or a class.

specialization, 模板特化

template <class Key>
struct hash { ...... };
template <>
struct hash<char> {
  size_t operator() (char x) const { return x; }
};

template <>
struct hash<int> {
  size_t operator() (int x) const { return x; }
}; 

template <>
struct hash<long> {
  size_t operator() (long x) const { return x; }
};

關(guān)于模板特化(摘自C++ Primer):

Redefinition of a class template, a member of a class template, or a function template, in which some (or all) of the template parameters are specified. A template specialization may not appear until after the base template that it specializes has been declared. A template specialization must appear before any use of the template with the specialized arguments. Each template parameter in a function template must be completely specialized.

partial specialization, 模板偏特化

  • 個(gè)數(shù)的偏:
// original class template:
template <typename T, typename Alloc = ......>
class vector {
...
};

// partial specialization:
template <typename Alloc = ......>
class vector <bool, Alloc> {
...
};
  • 范圍的偏:
// original class template:
template <typename T>
class C
{
// ...
};

// partial specialization:
template <typename T>
class C<T*>
{
// ...
};

關(guān)于模板偏特化(摘自C++ Primer):

Differently from function templates, a class template specialization does not have to supply an argument for every template parameter. We can specify some, but not all, of the template parameters or some, but not all, aspects of the parameters. A class template partial specialization is itself a template. Users must supply arguments for those template parameters that are not fixed by the specialization.

關(guān)于C++標(biāo)準(zhǔn)庫

點(diǎn)評(píng): 標(biāo)準(zhǔn)庫是C++重要的組成部分, 包括了容器, 迭代器, 算法和仿函數(shù). 這是一個(gè)極其巨大的話題, 三言兩語是無法解釋的. 完成了C++基礎(chǔ)語法的學(xué)習(xí)后, 應(yīng)好好參考侯捷老師的"那本STL源碼剖析".

variadic templates (since C++ 11)

void print()
{
}

template <typename T, typename... Types>
void print(const T &firstArg, const Types&... args) {
  cout << firstArg <<endl;
  print(args...);
}

print(7.5, "hello", bitset<16>(377), 42);
// OUTPUT:
// 7.5
// hello
// 0000000101111001
// 42

關(guān)于variadic templates(摘自 C++ Primer):

A variadic template is a template function or class that can take a varying number of parameters. The varying parameters are known as a parameter pack. There are two kinds of parameter packs: A template parameter pack represents zero or more template parameters, and a function parameter pack represents zero or more function parameters.

auto (since C++11)

list<string> c;
...

// before C++11
list<string>::iterator ite = find(c.begin(), c.end(), target);

// since C++11
auto                  ite2 = find(c.begin(). c.end(), target);

關(guān)于auto(摘自C++ Primer):

Under the new standard, we can let the compiler figure out the type for us by using the auto type specifier. Unlike type specifiers, such as double, that name a specific type, auto tells the compiler to deduce the type from the initializer. By implication, a variable that uses auto as its type specifier must have an initializer.

range-based for (since C++11)

for (int i : {2, 3, 5, 7, 9, 13, 17, 19}) {
  cout << i << endl;
}

vector<double> vec;
...
// pass by value
for (auto elem : vec) {
  cout << elem << endl;
}

// pass by reference
for (auto &elem : vec) {
  elem*=3;
}

關(guān)于range-based for(摘自C++ Primer):

If we want to do something to every character in a string, by far the best approach is to use a statement introduced by the new standard: the range for statement. This statement iterates through the elements in a given sequence and performs some operation on each value in that sequence. The syntactic form is
for (declaration : expression) { statement }
where expression is an object of a type that represents a sequence, and declaration defines the variable that we’ll use to access the underlying elements in the sequence. On each iteration, the variable in declaration is initialized from the value of the next element in expression .

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末萨惑,一起剝皮案震驚了整個(gè)濱河市滋戳,隨后出現(xiàn)的幾起案子懊缺,更是在濱河造成了極大的恐慌,老刑警劉巖屹逛,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件无牵,死亡現(xiàn)場離奇詭異姑尺,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)并蝗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門祭犯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人滚停,你說我怎么就攤上這事沃粗。” “怎么了键畴?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵最盅,是天一觀的道長。 經(jīng)常有香客問我起惕,道長涡贱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任惹想,我火速辦了婚禮盼产,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘勺馆。我一直安慰自己戏售,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布草穆。 她就那樣靜靜地躺著灌灾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悲柱。 梳的紋絲不亂的頭發(fā)上锋喜,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼嘿般。 笑死段标,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炉奴。 我是一名探鬼主播逼庞,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瞻赶!你這毒婦竟也來了赛糟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤砸逊,失蹤者是張志新(化名)和其女友劉穎璧南,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體师逸,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡司倚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了篓像。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片对湃。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖遗淳,靈堂內(nèi)的尸體忽然破棺而出拍柒,到底是詐尸還是另有隱情,我是刑警寧澤屈暗,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布拆讯,位于F島的核電站,受9級(jí)特大地震影響养叛,放射性物質(zhì)發(fā)生泄漏种呐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一弃甥、第九天 我趴在偏房一處隱蔽的房頂上張望爽室。 院中可真熱鬧,春花似錦淆攻、人聲如沸阔墩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啸箫。三九已至,卻和暖如春伞芹,著一層夾襖步出監(jiān)牢的瞬間忘苛,已是汗流浹背蝉娜。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扎唾,地道東北人召川。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像胸遇,于是被迫代替她去往敵國和親荧呐。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容