C是面向過程的語言甘耿,而C++是面向?qū)ο蟮拇瓴纭H绻荍ava開發(fā)者會(huì)更習(xí)慣與使用C++芽突,從Android系統(tǒng)源碼能看出试浙,Native層開發(fā)主要采用的也是C++,C語言更多的還是作為Kernel層的開發(fā)語言寞蚌。因此也有必要針對(duì)C++來做一個(gè)梳理田巴,從語言上,C++完全兼容C睬澡,很多東西都是相通的固额,因此與C相同的內(nèi)容就不再贅述。
一煞聪、命名空間
C++引入命名空間(namespace)斗躏,主要是避免命名沖突的問題。
namespace有系統(tǒng)定義的昔脯,也可以自定義啄糙。
舉例:
C++標(biāo)準(zhǔn)程序庫中的所有標(biāo)識(shí)符都被定義于一個(gè)名為std的namespace中。
使用C++打釉浦伞:
1)使用命名空間去點(diǎn)對(duì)應(yīng)標(biāo)識(shí)符:
std::cout << "Hello, World!" << std::endl;
2)使用命名空間對(duì)應(yīng)標(biāo)識(shí)符:
using std::cout;
using std::endl;
cout << "Hello, World!" << endl;
3)直接使用命名空間:
using namespace std;
cout << "Hello, World!" << endl;
二隧饼、引用與指針
C++在C指針的基礎(chǔ)上,增加引用的支持静陈。
引用是別名燕雁,指針是地址。二者區(qū)別:
- 指針可以被重新賦值以指向另一個(gè)不同的對(duì)象鲸拥。而引用則總是指向在初始化時(shí)被指定的對(duì)象拐格,以后不能改變,但是指定的對(duì)象其內(nèi)存可以改變刑赶。
- 程序?yàn)橹羔樧兞糠峙鋬?nèi)存區(qū)域捏浊,可以指向空值。而不為引用分配內(nèi)存區(qū)域撞叨,不可指向空值金踪。
舉例:
//指針傳遞
void swap(int *a, int *b) {
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
//引用傳遞
void swap1(int &a, int &b) {
int tmp;
tmp = a;
a = b;
b = tmp;
}
int main() {
int a = 1;
int b = 2;
swap(&a, &b);
swap1(a, b);
return 0;
}
二、字符串
C++引入string
#include <string>
int main() {
string str = "hello";
cout << str << endl;
return 0;
}
三牵敷、面向?qū)ο?/h4>
這部分是C++區(qū)別于C的核心內(nèi)容胡岔。
3.1 類與對(duì)象
class Shape {
/**
* 訪問修飾符
* public
* private 只有類和友元函數(shù)可以訪問私有成員
* protect 類、友元函數(shù)枷餐、子類可以訪問受保護(hù)成員
*/
public:
//無參構(gòu)造方法(直接實(shí)現(xiàn))
Shape() {
};
//帶參構(gòu)造方法聲明(外部實(shí)現(xiàn))
Shape(double len);
//析構(gòu)函數(shù)
~Shape() {
//在每次刪除所創(chuàng)建的對(duì)象時(shí)執(zhí)行, 主要做些釋放資源的事
}
//靜態(tài)成員
static int objectCount;
//成員變量
int width;
int height;
//成員函數(shù)聲明(外部實(shí)現(xiàn))
int getArea1();
//成員函數(shù)直接實(shí)現(xiàn)
int getArea2() {
return 0;
}
/**
* 友元函數(shù):類的友元函數(shù)是實(shí)現(xiàn)在類外部的姐军,但具有訪問類private和protected的成員變量與函數(shù)
* 注意:
* 友元函數(shù)不能使用this
* 友元函數(shù)不能被子類繼承
* @param shape
*/
friend void printLength(Shape shape);
protected:
int length;
private:
void show() {
cout << "show" << endl;
}
};
//成員函數(shù)定義
int Shape::getArea1() {
return 0;
}
//帶參構(gòu)造方法
Shape::Shape(double width) {
this->width = width;
cout << "constructor create:length " << width << endl;
}
//友元函數(shù)實(shí)現(xiàn)
void printLength(Shape shape) {
cout << "length:" << shape.length << endl;
shape.show();
}
//初始化靜態(tài)變量
int Shape::objectCount = 1;
int main() {
//無參構(gòu)造函數(shù)
Shape shape;
//有參構(gòu)造函數(shù)三種調(diào)用方法:
Shape shape1(1.23);
Shape shape2 = (1.23);
Shape shape3 = Shape(1.23);
cout << "objectCount:" << Shape::objectCount << endl;
printLength(shape);
return 0;
}
淺拷貝:拷貝指針變量的值。
深拷貝:拷貝指針?biāo)赶虻膬?nèi)存空間尖淘。
3.2 抽象類與繼承
class Shape {
public:
//純虛函數(shù), =0 告訴編譯器奕锌,函數(shù)沒有主體
virtual int getArea() = 0;
protected:
int width = 1;
int height = 2;
};
//派生子類
//多繼承:class <派生類名>:<訪問控制1><基類名1>,<訪問控制2><基類名2>,…
class Rectangle : public Shape {
public:
int getArea() {
return width * height;
}
};
int main() {
Rectangle rect;
cout << rect.getArea() << endl;
}
類中至少有一個(gè)函數(shù)被聲明為純虛函數(shù),則這個(gè)類就是抽象類村生。
抽象類不能被用于實(shí)例化對(duì)象惊暴,它只能作為接口使用。
3.3 重載
函數(shù)重載
class printData
{
public:
//print重載
void print(int i) {
cout << "整數(shù)為: " << i << endl;
}
void print(double f) {
cout << "浮點(diǎn)數(shù)為: " << f << endl;
}
};
運(yùn)算符重載
class Shape {
public:
int width = 1;
Shape() {}
Shape(int w) {
width = w;
}
//重載 + 運(yùn)算符趁桃,用于把兩個(gè)Shape對(duì)象相加
Shape operator+(const Shape &shape) {
Shape s;
s.width = width + shape.width;
return s;
}
};
int main() {
Shape shape;
Shape shape1 = Shape(2);
const Shape &s = shape.operator+(shape1);
cout << s.width << endl;
}
支持重載的運(yùn)算符:
雙目算術(shù)運(yùn)算符: + 辽话,-,卫病,/油啤,%
關(guān)系運(yùn)算符: ==,!=蟀苛, < 益咬,> ,<=帜平,>=
邏輯運(yùn)算符: ||幽告,&&,!
單目運(yùn)算符: + 裆甩,-冗锁,,&
自增自減運(yùn)算符: ++嗤栓,--
位運(yùn)算符: | 冻河,& ,~茉帅,^叨叙,<< ,>>
賦值運(yùn)算符: =, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=
空間申請(qǐng)與釋放: new, delete, new[ ] , delete[]
其他運(yùn)算符: ()(函數(shù)調(diào)用)担敌,->(成員訪問)摔敛,,(逗號(hào)),
3.4 多態(tài)
配合虛函數(shù)實(shí)現(xiàn)多態(tài)
class Shape {
public:
//虛函數(shù)
virtual int area() {
cout << "Parent class area :" << endl;
return 0;
}
};
class Rectangle : public Shape {
public:
int area() {
cout << "Rectangle class area" << endl;
}
};
class Triangle : public Shape {
public:
int area() {
cout << "Triangle class area" << endl;
}
};
int main() {
//父類指針指向不同子類對(duì)象地址全封,這是C++多態(tài)一般使用方式
Shape *shape;
Rectangle rectangle;
Triangle triangle;
shape = &rectangle;
shape->area();
shape = ▵
shape->area();
}
四马昙、動(dòng)態(tài)內(nèi)存分配
C++中使用new和delete來動(dòng)態(tài)分配和釋放內(nèi)存。malloc() 函數(shù)在 C 語言中就出現(xiàn)了刹悴,在 C++ 中仍然存在行楞,new 與 malloc() 函數(shù)相比,其主要的優(yōu)點(diǎn)是:new 不僅分配了內(nèi)存土匀,它還創(chuàng)建了對(duì)象子房。
//為對(duì)象動(dòng)態(tài)分配內(nèi)存
Shape *pShape = new Shape();
//為對(duì)象釋放內(nèi)存
delete pShape;
五、信號(hào)處理
#include <signal.h>
static void signalHandler(int signum) {
cout << "abort signal (" << signum << ") received.\n";
exit(signum);
}
int main() {
// 注冊(cè)信號(hào) SIGINT 和信號(hào)處理程序,因?yàn)樗⒉粚儆赑OSIX(Portable Operating System Interface)標(biāo)準(zhǔn),即:可移植操作系統(tǒng)接口
// 在各類 UNIX 平臺(tái)上的實(shí)現(xiàn)不盡相同,因此其用途受到了一定的限制证杭。
signal(SIGABRT, signalHandler);
/**
* sigaction 結(jié)構(gòu)體
*
* sa_handler: 設(shè)置處理函數(shù)handler
* sig.sa_sigaction: 也是設(shè)置處理函數(shù)handler田度,但是與sa_handler對(duì)應(yīng)的handler傳參不一樣
* sa_mask: 用來設(shè)置在處理該信號(hào)時(shí)暫時(shí)將sa_mask指定的信號(hào)集擱置
* sa_flags:
* SA_ONSTACK 0x0001 take signal on signal stack
* SA_RESTART 0x0002 restart system on signal return
* SA_RESETHAND 0x0004 reset to SIG_DFL when taking signal
* SA_NOCLDSTOP 0x0008 do not generate SIGCHLD on child stop
* SA_NODEFER 0x0010 don't mask the signal we're delivering
* SA_NOCLDWAIT 0x0020 don't keep zombies around
* SA_SIGINFO 0x0040 signal handler with SA_SIGINFO args
*/
struct sigaction sig;
sig.sa_flags = SA_RESETHAND;
sig.sa_handler = signalHandler;
/**
* int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
*
* signum: 要操作的信號(hào)
* act: 新的對(duì)信號(hào)的處理方式
* oldact: 原來對(duì)信號(hào)的處理方式
* return: 0表示成功,-1表示有錯(cuò)誤發(fā)生
*/
sigaction(SIGABRT, &sig, NULL);
abort();
}
六、模板
類似java泛型
6.1 函數(shù)模板
template<typename T>
void swap_(T &a, T &b){
T temp = a;
a = b;
b = temp;
}
int main(){
//交換 int 變量的值
int n1 = 100, n2 = 200;
swap_(n1, n2);
cout<<n1<<", "<<n2<<endl;
//交換 float 變量的值
float f1 = 12.5, f2 = 56.93;
swap_(f1, f2);
cout<<f1<<", "<<f2<<endl;
return 0;
}
6.2 類模板
template<typename T1, typename T2> //這里不能有分號(hào)
class Point
{
public:
Point(T1 x, T2 y): m_x(x), m_y(y){ }
public:
T1 getX() const; //獲取x坐標(biāo)
void setX(T1 x); //設(shè)置x坐標(biāo)
T2 getY() const; //獲取y坐標(biāo)
void setY(T2 y); //設(shè)置y坐標(biāo)
private:
T1 m_x; //x坐標(biāo)
T2 m_y; //y坐標(biāo)
};
typename也可以用class
七解愤、類型轉(zhuǎn)換
轉(zhuǎn)換類型操作符 | 作用 |
---|---|
const_cast | 去掉類型的const或volatile屬性镇饺。 |
static_cast | 無條件轉(zhuǎn)換,靜態(tài)類型轉(zhuǎn)換送讲。 |
dynamic_cast | 有條件轉(zhuǎn)換奸笤,動(dòng)態(tài)類型轉(zhuǎn)換,運(yùn)行時(shí)檢查類型安全(轉(zhuǎn)換失敗返回NULL)哼鬓。 |
reinterpret_cast | 僅重新解釋類型监右,但沒有進(jìn)行二進(jìn)制的轉(zhuǎn)換。 |
使用舉例:
class Person {
public:
Person() {}
~Person() {}
int age;
virtual void character() {};
};
class Student : public Person {
public:
int classId;
};
void func() {}
typedef void(*FuncPtr)();//函數(shù)指針
int main() {
//const_cast
const Person p;
//p.age = 10;//不能直接修改const類型
Person per = const_cast<Person &>(p);
per.age = 10;
cout << "age:" << per.age << endl;
//static_cast
int n = 6;
double d = static_cast<double>(n); //基本類型轉(zhuǎn)換
//dynamic_cast
Person *person = new Student();
Student *stu = dynamic_cast<Student *>(person);//子類->父類异希,動(dòng)態(tài)類型轉(zhuǎn)換
//reinterpret_cast
FuncPtr funcPtr = reinterpret_cast<FuncPtr>(&func);//不同函數(shù)指針類型之間進(jìn)行轉(zhuǎn)換
}
總結(jié):
- 去const屬性用const_cast
- 基本類型轉(zhuǎn)換用static_cast
- 多態(tài)類之間的類型轉(zhuǎn)換用dynamic_cast
- 不同類型的指針類型轉(zhuǎn)換用reinterpret_cast
未完待續(xù)...