C++的歷史與演化
C++起先是在C語(yǔ)言上面的一種拓展,后來(lái)演化到現(xiàn)在,已經(jīng)是一門(mén)獨(dú)立且備受矚目的語(yǔ)言了。
語(yǔ)言關(guān)系圖: B -> C -> C++(new C -> C with class -> C++
演化路線圖: C++98 -> C++03 -> C++11 -> C++14
C++的幾種模式
C++本身被視作一個(gè)語(yǔ)言的聯(lián)邦,本身是一種多范型的語(yǔ)言。學(xué)好C++,需要了解一下的幾種C++的常用范型。
- Clean C
- Object-Oriented C++
- Template C++
- STL
C++原本的翻譯作為C plus plus, 第一版語(yǔ)言本身可以被稱作為C with Class。 對(duì)于Class這個(gè)名詞而言,C++有可以區(qū)分為OBP && OOP。
OBP本身是利用了C++對(duì)Data Resource的一種封裝,這里一般就是單個(gè)Class而已,很少與其他Class發(fā)生較多的交互。而OOP本身更多的使用了繼承與多態(tài),而且OOP更加注重于Class與Class之間的關(guān)系。Class與Class之間的關(guān)系有繼承(inheritance),復(fù)合(composition)和委托(delegation)。
C++代碼的基本結(jié)構(gòu)
C++的代碼一般分為聲明部分 && 實(shí)現(xiàn)部分。
聲明部分一般存放在.h .hpp結(jié)尾的文件中。 實(shí)現(xiàn)部分一般存放在.cc .cpp .C結(jié)尾的文件中。
為什么這里要區(qū)分聲明 && 實(shí)現(xiàn)呢。因?yàn)橐粋€(gè)項(xiàng)目不可能只有一個(gè)文件,一般一個(gè)工程是多人協(xié)作式的。首先單個(gè)文件無(wú)法多人進(jìn)行編輯。第二,如果每個(gè)人負(fù)責(zé)項(xiàng)目的一個(gè)模塊,一個(gè)只要關(guān)心自己的部分和他人與自己相關(guān)的部分了。如果實(shí)現(xiàn)與聲明相分離,相關(guān)的人員只需要在開(kāi)發(fā)的時(shí)候約定聲明的部分,可以在開(kāi)發(fā)過(guò)程中不關(guān)心實(shí)現(xiàn),到最后進(jìn)行代碼的集成測(cè)試就可以了。
C++的聲明文件為了防止多次包含有兩種技巧。一種是防御式聲明(ifndef), 一種使用#pragma once
- 防御式聲明
// hello.h
#ifndef HELLO_H_
#define HELLO_H_
#endif // HELLO_H_
- pragma
// hello.h
#pragma once
C++ Class
一般認(rèn)為C++本身包括了C語(yǔ)言部分即Clean C。C語(yǔ)言的聲明 && 控制,C++基本與其類(lèi)似。
C++的Class一般包含了構(gòu)造與析構(gòu)部分。構(gòu)造是用來(lái)初始化一個(gè)對(duì)象,析構(gòu)是對(duì)象生命周期結(jié)束后告訴編譯器如何刪除一個(gè)對(duì)象。構(gòu)造函數(shù)和析構(gòu)函數(shù)屬于特殊的函數(shù)。這兩種函數(shù)都是沒(méi)有返回值的。
C++的對(duì)象如果名稱叫做complex,那么構(gòu)造函數(shù)就是complex(...), ...表示參數(shù)列表, 這里可以看出complex是可以有多個(gè)的,本身可以被重載。 析構(gòu)函數(shù)就是~complex,析構(gòu)函數(shù)是沒(méi)有參數(shù)列表的。C++如果不聲明構(gòu)造函數(shù)或者析構(gòu)函數(shù)的話。編譯器本身會(huì)給合成一個(gè)構(gòu)造或者析構(gòu)函數(shù)。合成的構(gòu)造函數(shù)是沒(méi)有參數(shù)列表的。如果一個(gè)類(lèi)中含有指針,最好自定義析構(gòu)函數(shù),否則合成的析構(gòu)函數(shù)不會(huì)delete指針?biāo)鶎?duì)應(yīng)的對(duì)象。
class complex {
public:
complex(int re, int im); // 構(gòu)造函數(shù)
~complex(); // 析構(gòu)函數(shù)
private:
int re_, im_;
};
C++本身也有權(quán)限控制比如public, private, protected。
public表示在類(lèi)以外也能被訪問(wèn),而private表示只能在類(lèi)中被訪問(wèn)。protected表示在被繼承的類(lèi)中能夠被直接訪問(wèn)。class默認(rèn)是private類(lèi)型的,struct 默認(rèn)是public類(lèi)型的。這個(gè)是class/struct聲明的兩者的根本區(qū)別。
這里有一個(gè)特點(diǎn)如果構(gòu)造函數(shù)在private區(qū)域可以被用來(lái)實(shí)現(xiàn)單例模式。
// singleton
#include <iostream>
using namespace std;
class Singleton {
Singleton() {}
static Singleton *instance;
public:
~Singleton() { cout << "Singleton dtor" << endl; }
struct GC {
~GC() { if(instance) { cout << "Delete Singleton" << endl; delete instance; } }
};
private:
static GC gc;
public:
static Singleton *Instance() {
if (!instance) {
instance = new Singleton;
}
return instance;
}
};
Singleton *Singleton::instance = NULL;
Singleton::GC gc;
int main()
{
Singleton *s = Singleton::Instance();
// delete t;
return 0;
}
在C++中一個(gè)member function也可以是const的,這里表示this指針是const,所以不能修改類(lèi)實(shí)例的成員變量的值。const的類(lèi)實(shí)例變量只能調(diào)用const 方法
class complex {
public:
complex(double r = 0, double i = 0) : re(r), im(i) {}
complex &operator+=(const complex &);
complex &operator-=(const complex &);
complex &operator*=(const complex &);
complex &operator/=(const complex &);
double real() const { return re; }
double imag() const { return im; }
private:
double re, im;
friend complex &__doapl(complex *, const complex &);
friend complex &__doami(complex *, const complex &);
friend complex &__doaml(complex *, const complex &);
};
{
const complex c(1, 2);
cout << c.real() << endl;
}
C++的函數(shù)傳值
- pass by value
通過(guò)值來(lái)傳遞給調(diào)用的函數(shù),此時(shí)在調(diào)用的函數(shù)修改了值,原先的變量的值還是不會(huì)改變
void fun(int a)
{
a += 1;
}
{
int a = 10;
fun(a);
cout << a << endl; // 10 not 11
}
- pass by reference/pointer
通過(guò)引用來(lái)傳值,這里如果在調(diào)用的函數(shù)中修改了值,原先的值也會(huì)被修改。reference 編譯器的實(shí)現(xiàn)實(shí)際上是一個(gè)const pointer。
void fun(int a)
{
a += 1;
}
{
int a = 10;
fun(a);
cout << a << endl; // 11 not 10
}
Operator Overloading
C++自定義類(lèi)型的一些operator是可以被重載的,比如+,+=,++,但是基本類(lèi)型的是不可以的,這個(gè)會(huì)引起底層的混亂。
op any of the following 38 operators:+ - * / % ? & | ~ ! = < > += -= *= /= %= ?= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> ( ) [ ]
1) overloaded operator;
2) [user-defined conversion function](http://en.cppreference.com/w/cpp/language/cast_operator);
3) [allocation function](http://en.cppreference.com/w/cpp/memory/new/operator_new);
4) [deallocation function](http://en.cppreference.com/w/cpp/memory/new/operator_delete);
5) [user-defined literal](http://en.cppreference.com/w/cpp/language/user_literal).
Synatax
operator op (1)
operator type (2)
operator new
operator new [] (3)
operator delete
operator delete [] (4)
operator "" suffix-identifier (5) (since C++11)
in this table, @ is a placeholder representing all matching operators: all prefix operators in @a, all postfix operators other than -> in a@, all infix operators other than = in a@b
C++臨時(shí)變量
C++的臨時(shí)變量的產(chǎn)生一般和函數(shù)調(diào)用相關(guān),一個(gè)調(diào)用如果沒(méi)有被一個(gè)左值接受,那么就可產(chǎn)生一個(gè)臨時(shí)變量,這個(gè)變量的生命周期是這條語(yǔ)句。這種變量在functor , 鏈?zhǔn)秸{(diào)用 和 一些使用到RAII的手法中經(jīng)常會(huì)被使用到(比如Logger class)。臨時(shí)變量實(shí)際上和左值,右值有著密切的關(guān)系,以后有機(jī)會(huì)再詳細(xì)說(shuō)明。
#include <iostream>
using namespace std;
class Temp {
public:
Temp(int t) : t_(t) {}
~Temp() { cout << t_ << endl; }
private:
int t_;
};
int main()
{
cout << "---------- Begin ----------" << endl;
Temp(1); // 1
Temp(2); // 2
cout << "---------- End ----------" << endl;
return 0;
}
/*
output:
---------- Begin ----------
1
2
---------- End ----------
*/
// 這里1,2在End之前被打印出來(lái),可以看出臨時(shí)變量的聲明周期就只有單條語(yǔ)句
總結(jié)
在這次課程中,我對(duì)對(duì)過(guò)去的知識(shí)做了一個(gè)完整的梳理與總結(jié)。感覺(jué)還是很不錯(cuò)的。以后還需要認(rèn)真學(xué)習(xí)。