語法基礎(chǔ)——C++語法基礎(chǔ)

前言

最近發(fā)現(xiàn)要學(xué)習(xí)C++來開發(fā)NDK誓篱,不得不把基礎(chǔ)的東西記錄下來,否則學(xué)的太多會混淆笼沥,廢話不多說蚪燕,開始記錄我的C++學(xué)習(xí)之旅吧

HelloWord

導(dǎo)庫

命名空間

輸出函數(shù)

#include <iostream>

//必須帶有命名空間才能使用cout等

using namespace std;

int main()

{

? ? cout << "Hello, world!" << endl;

? ? return 0;

}

命名空間

1、命名空間屬性訪問和結(jié)構(gòu)體訪問

namespace NSP_A{

? ? int a = 9;

? ? struct Student{

? ? ? ? char name[20];

? ? ? ? int age;

? ? };

}

void main(){

? ? //使用命名空間

? ? cout << NSP_A::a << endl;

? ? //使用命名空間中的結(jié)構(gòu)體

? ? using NSP_A::Student;

? ? Student t;

}

2奔浅、命名空間的嵌套

namespace NSP_B{

? ? //命名空間嵌套

? ? namespace NSP_C{

? ? ? ? int c = 90;

? ? }

}

void main(){

? ? cout << NSP_B::NSP_C::c << endl;

}

1馆纳、類、屬性汹桦、方法的聲明與使用

#define _CRT_SECURE_NO_WARNINGS

#include <stdlib.h>

#include <iostream>

#include <stdarg.h>

using namespace std;

#define PI 3.14

class MyCircle{

//屬性(共用權(quán)限訪問修飾符)

private:

? ? double r;

? ? double s;

public:

? ? void setR(double r){

? ? ? ? this->r = r;

? ? }

? ? //獲取面積

? ? double getS(){

? ? ? ? return PI * r * r;

? ? }

};

void main(){

? ? MyCircle c;

? ? c.setR(4);

? ? cout << "圓的面積:" << c.getS() << endl;

? ? system("pause");

}

2鲁驶、類的大小

類的大小只計算普通屬性的大小,其他都不包括在內(nèi)

class A{

public:

? ? int i;

? ? int j;

? ? int k;

? ? static int m;

};

class B{

public:

? ? int i;

? ? int j;

? ? int k;

? ? void myprintf(){

? ? ? ? cout << "打印" << endl;

? ? }

};

void main(){

? ? //輸出的結(jié)果都是12

? ? cout << sizeof(A) << endl;

? ? cout << sizeof(B) << endl;

}


繼承

1舞骆、繼承基本使用

class Human{

public:

? ? void say(){

? ? ? ? cout << "說話" << endl;

? ? }

protected:

? ? int age;? ?

};

class Man : public Human{

};

void main(){

? ? //子類

? ? Man m1;

? ? m1.say();

? ? //將子類賦值給父類的引用或指針

? ? Human* h_p = &m1;

? ? h_p->say();

? ? Human &h1 = m1;

? ? h1.say();

? ? //子類對象初始化父類類型的對象

? ? Human h2 = m1;

? ? h2.say();

? ? //子類對象調(diào)用父類的成員

? ? m1.Human::say();

? ? m1.Human::age = 10;

}

2钥弯、向父類構(gòu)造方法傳參

class Human{

public:

? ? Human(char* name, int age){

? ? ? ? this->name = name;

? ? ? ? this->age = age;

? ? }

protected:

? ? char* name;

? ? int age;

};

class Man : public Human{

public:

? ? //給父類構(gòu)造函數(shù)傳參径荔,同時給屬性h對象賦值

? ? Man(char *brother, char *s_name, int s_age, char *h_name, int h_age) : Human(s_name, s_age), h(h_name,h_age){

? ? ? ? this->brother = brother;

? ? }

private:

? ? Human h;

};

void main(){

? ? Man m1("Hensen","HensenBoy",18,"HensenGirl",18);

}

3、多繼承的實現(xiàn)

class Person{

};

class Citizen{

};

class Student : public Person, public Citizen{

};

4脆霎、繼承間的訪問修飾符

基類中? ? ? ? 繼承方式? ? ? ? 子類中

public? ? & public繼承 = > public

public? ? & protected繼承 = > protected

public? ? & private繼承 = > private

protected? & public繼承 = > protected

protected? & protected繼承 = > protected

protected? & private繼承 = > private

private? ? & public繼承 = > 子類無權(quán)訪問

private? ? & protected繼承 = > 子類無權(quán)訪問

private? ? & private繼承 = > 子類無權(quán)訪問


5总处、繼承的二義性

virtual:表示虛繼承,不同路徑繼承來的同名成員只有一份拷貝睛蛛,解決不明確的問題

class A{

public:

? ? char* name;

};

//這里面加了virtual關(guān)鍵字

class A1 : virtual public A{

};

//這里面加了virtual關(guān)鍵字

class A2 : virtual public A{

};

class B : public A1, public A2{

};

void main(){

? ? B b;? ?

? ? //如果程序不加virtual關(guān)鍵字就會導(dǎo)致二義性鹦马,系統(tǒng)無法辨識哪個類的name屬性,會報錯

? ? b.name = "Hensen";

? ? //這里通過指定父類顯示調(diào)用是可以的

? ? b.A1::name = "Hensen";

? ? b.A2::name = "Hensen";

}

多態(tài)

1忆肾、多態(tài)的基本使用

//Plane.h文件

#pragma once

//普通飛機

class Plane{

public:

? ? virtual void fly();

? ? virtual void land();

};

//Plane.cpp文件

#include "Plane.h"

#include <iostream>

using namespace std;

void Plane::fly(){

? ? cout << "起飛" << endl;

}

void Plane::land(){

? ? cout << "著陸" << endl;

}

//Jet.h文件

#pragma once

#include "Plane.h"

//直升飛機

class Jet : public Plane{

? ? virtual void fly();

? ? virtual void land();

};

//Jet.cpp文件

#include "Jet.h"

#include <iostream>

using namespace std;

void Jet::fly(){

? ? cout << "直升飛機在原地起飛..." << endl;

}

void Jet::land(){

? ? cout << "直升飛機降落在女神的屋頂..." << endl;

}

#include "Plane.h"

#include "Jet.h"

#include "Copter.h"

//業(yè)務(wù)函數(shù)

void bizPlay(Plane& p){

? ? p.fly();

? ? p.land();

}

void main(){

? ? Plane p1;

? ? bizPlay(p1);

? ? //直升飛機

? ? Jet p2;

? ? bizPlay(p2);

}

引用

1荸频、引用的使用

void main(){

? ? int a = 10;

? ? //&是C++中的引用,引用:變量的另外一個別名难菌,共用同個地址

? ? int &b = a;

? ? cout << b << endl;

}

2试溯、引用與指針的區(qū)別

不存在空引用,引用必須連接到一塊合法的內(nèi)存郊酒。

一旦引用被初始化為一個對象遇绞,就不能被指向到另一個對象。指針可以在任何時候指向到另一個對象燎窘。

引用必須在創(chuàng)建時被初始化摹闽。指針可以在任何時間被初始化。

3褐健、引用與指針寫法上的差異

struct Teacher{

? ? char* name;

? ? int age;

};

//帶有結(jié)構(gòu)體指針的寫法

void myprint(Teacher *t){

? ? cout << t->name << "," << t->age << endl;?

? ? //(*t).name

}

//帶有結(jié)構(gòu)體引用的寫法

void myprint2(Teacher &t){

? ? cout << t.name << "," << t.age << endl;

? ? t.age = 21;

}

//指針值交換

void swap_1(int *a, int *b){

? ? int c = 0;

? ? c = *a;

? ? *a = *b;

? ? *b = c;

}

//引用值交換

void swap_2(int &a, int &b){

? ? int c = 0;

? ? c = a;

? ? a = b;

? ? b = c;

}

void main(){

? ? Teacher t;

? ? t.name = "Hensen";

? ? t.age = 20;

? ? //指針的寫法

? ? myprint(&t);

? ? //引用的寫法

? ? myprint2(t);

? ? int x = 10;

? ? int y = 20;

? ? //指針的寫法

? ? swap_1(&x, &y);

? ? //引用的寫法

? ? swap_2(x,y);

}


4付鹿、引用的作用

把引用作為參數(shù):C++支持把引用作為參數(shù)傳給函數(shù),這比傳一般的參數(shù)更安全

把引用作為返回值:可以從C++函數(shù)中返回引用蚜迅,就像返回其他數(shù)據(jù)類型一樣

5舵匾、指針引用,代替二級指針

struct Teacher{

? ? char* name;

? ? int age;

};

//引用的寫法

void getTeacher(Teacher* &p){

? ? p = (Teacher*)malloc(sizeof(Teacher));

? ? p->age = 20;

}

//二級指針的寫法谁不,原本應(yīng)該這樣寫坐梯,但是已經(jīng)被引用的寫法代替了

void getTeacher(Teacher **p){

? ? Teacher *tmp = (Teacher*)malloc(sizeof(Teacher));

? ? tmp->age = 20;

? ? *p = tmp;

}

void main(){

? ? Teacher *t = NULL;

? ? //傳遞引用的指針t,相當(dāng)于二級指針

? ? getTeacher(&t);

}

6刹帕、常引用吵血,類似于java中final

//常引用在方法中的引用

void myprint(const int &a){

? ? cout << a << endl;?

}

void main(){? ?

? ? //引用必須要有值,不能為空偷溺,下面寫法是錯誤的

? ? //const int a;

? ? //int &a = NULL;

? ? //常引用屬性使用一

? ? int a = 10, b = 9;

? ? const int &c = a;

? ? //常引用屬性使用二

? ? const int &d = 70;

}

7蹋辅、引用與指針的大小

struct Teacher{

? ? char name[20];

? ? int age;

};

void main(){

? ? Teacher t;

? ? //引用

? ? Teacher &t1 = t;

? ? //指針

? ? Teacher *p = &t;

? ? //結(jié)果是24,引用相當(dāng)于變量的別名

? ? cout << sizeof(t1) << endl;

? ? //結(jié)果是4挫掏,指針只是存放的地址

? ? cout << sizeof(p) << endl;

? ? system("pause");

}

異常

1侦另、C++異常處理,會根據(jù)拋出的異常數(shù)據(jù)類型,進(jìn)入到相應(yīng)的catch塊中

void main(){

? ? try{

? ? ? ? int age = 300;

? ? ? ? if (age > 200){

? ? ? ? ? ? throw 9.8;

? ? ? ? }

? ? }

? ? catch (int a){

? ? ? ? cout << "int異常" << endl;

? ? }

? ? catch (char* b){

? ? ? ? cout << b << endl;

? ? }

? ? catch (...){

? ? ? ? cout << "未知異常" << endl;

? ? }

}

2淋肾、向下拋出異常

void mydiv(int a, int b){

? ? if (b == 0){

? ? ? ? throw "除數(shù)為零";

? ? }

}

void func(){

? ? try{

? ? ? ? mydiv(8, 0);

? ? }

? ? catch (char* a){

? ? ? ? throw a;

? ? }

}

void main(){

? ? try{

? ? ? ? func();

? ? }

? ? catch (char* a){

? ? ? ? cout << a << endl;

? ? }

}

3硫麻、拋出對象

class MyException{

};

void mydiv(int a, int b){

? ? if (b == 0){

? ? ? ? throw MyException();

? ? ? ? //不要拋出異常指針

? ? ? ? //throw new MyException;? ? ? ?

? ? }

}

void main(){

? ? try{

? ? ? ? mydiv(8,0);

? ? }

? ? catch (MyException& e2){

? ? ? ? cout << "MyException引用" << endl;

? ? }

? ? catch (MyException* e1){

? ? ? ? cout << "MyException指針" << endl;? ? ? ?

? ? ? ? //指針的話需要手動釋放內(nèi)存

? ? ? ? delete e1;

? ? }

}

4爸邢、方法拋出異常

void mydiv(int a, int b) throw (char*, int) {

? ? if (b == 0){

? ? ? ? throw "除數(shù)為零";?

? ? }

}

5樊卓、標(biāo)準(zhǔn)異常

//需要導(dǎo)入標(biāo)準(zhǔn)異常的依賴庫

#include<stdexcept>

class NullPointerException : public exception{

public:

? ? NullPointerException(char* msg) : exception(msg){

? ? }

};

void mydiv(int a, int b){

? ? if (b > 10){

? ? ? ? throw out_of_range("超出范圍");? ?

? ? }?

? ? else if (b == NULL){

? ? ? ? throw NullPointerException("為空");

? ? }

? ? else if (b == 0){

? ? ? ? throw invalid_argument("參數(shù)不合法");

? ? }

}

void main(){

? ? try{

? ? ? ? mydiv(8,NULL);

? ? }

? ? catch (out_of_range e1){

? ? ? ? cout << e1.what() << endl;

? ? }

? ? catch (NullPointerException& e2){

? ? ? ? cout << e2.what() << endl;

? ? }

? ? catch (...){

? ? ? ? cout << "未知異常" << endl;

? ? }

}

6、外部類異常

class Err{

public:

? ? class MyException{

? ? ? ? public:MyException(){

? ? ? ? }

? ? };

};

void mydiv(int a, int b){

? ? if (b > 10){

? ? ? ? throw Err::MyException();

? ? }

}

IO流

1杠河、普通文件

#include <iostream>

#include <fstream>

void main(){

? ? char* fname = "c://dest.txt";

? ? //輸出流

? ? ofstream fout(fname);

? ? //創(chuàng)建失敗

? ? if (fout.bad()){

? ? ? ? return;

? ? }

? ? //寫入文件

? ? fout << "Hensen" << endl;

? ? //關(guān)閉輸出流

? ? fout.close();

? ? //輸入流

? ? ifstream fin(fname);

? ? //創(chuàng)建失敗

? ? if (fin.bad()){

? ? ? ? return;

? ? }

? ? char ch;

? ? //讀取數(shù)據(jù)

? ? while (fin.get(ch)){

? ? ? ? cout << ch;

? ? }

? ? //關(guān)閉輸入流

? ? fin.close();

}

2碌尔、二進(jìn)制文件

void main(){

? ? char* src = "c://src.jpg";

? ? char* dest = "c://dest.jpg";

? ? //輸入流

? ? ifstream fin(src, ios::binary);

? ? //輸出流

? ? ofstream fout(dest, ios::binary);

? ? if (fin.bad() || fout.bad()){

? ? ? ? return;

? ? }

? ? while (!fin.eof()){

? ? ? ? //讀取

? ? ? ? char buff[1024] = {0};

? ? ? ? fin.read(buff,1024);

? ? ? ? //寫入

? ? ? ? fout.write(buff,1024);

? ? }

? ? //關(guān)閉

? ? fin.close();

? ? fout.close();

}

3、C++對象的持久化

class Person

{

public:

? ? Person()

? ? {

? ? }

? ? Person(char * name, int age)

? ? {

? ? ? ? this->name = name;

? ? ? ? this->age = age;

? ? }

? ? void print()

? ? {

? ? ? ? cout << name << "," << age << endl;

? ? }

private:

? ? char * name;

? ? int age;

};

void main()

{

? ? Person p1("Hensen", 22);

? ? Person p2("HensenBoy", 18);

? ? //輸出流

? ? ofstream fout("c://c_obj.data", ios::binary);

? ? fout.write((char*)(&p1), sizeof(Person));

? ? fout.write((char*)(&p2), sizeof(Person));

? ? fout.close();

? ? //輸入流

? ? ifstream fin("c://c_obj.data", ios::binary);

? ? Person tmp;

? ? fin.read((char*)(&tmp), sizeof(Person));

? ? tmp.print();

? ? fin.read((char*)(&tmp), sizeof(Person));

? ? tmp.print();

}

函數(shù)

1券敌、函數(shù)的重載

函數(shù)可以傳默認(rèn)值參數(shù)唾戚,如果調(diào)用存在參數(shù),則默認(rèn)參數(shù)會被替代

void myprint(int x, int y = 9, int z = 8){

? ? cout << x << endl;

}

//重載

void myprint(int x,bool ret){

? ? cout << x << endl;

}

void main(){

? ? myprint(20);

? ? //覆蓋默認(rèn)參數(shù)的9和8

? ? myprint(20,10,5);

}

2待诅、可變參數(shù)函數(shù)

void func(int i,...)

{

? ? //可變參數(shù)指針

? ? va_list args_p;

? ? //可變參數(shù)設(shè)置開始位置

? ? //i表示可變參數(shù)的前一位參數(shù)叹坦,從i開始,后面的就是可變參數(shù)

? ? va_start(args_p,i);

? ? int a = va_arg(args_p,int);

? ? char b = va_arg(args_p, char);

? ? int c = va_arg(args_p, int);

? ? cout << a << endl;

? ? cout << b << endl;

? ? cout << c << endl;

? ? //可變參數(shù)設(shè)置結(jié)束

? ? va_end(args_p);

}

void main(){

? ? //使用

? ? func(9,20,'b',30);

}

可變參數(shù)也可以循環(huán)讀取卑雁,但是必須保證所有數(shù)大于0使用

void func(int i,...)

{

? ? va_list args_p;

? ? //開始

? ? va_start(args_p,i);

? ? int value;

? ? while (1){

? ? ? ? value = va_arg(args_p,int);

? ? ? ? if (value <= 0){

? ? ? ? ? ? break;

? ? ? ? }

? ? ? ? cout << value << endl;

? ? }

? ? //結(jié)束

? ? va_end(args_p);

}

3募书、靜態(tài)屬性和方法

class Teacher{

public:

? ? char* name;

? ? //計數(shù)器

? ? static int total;

public:

? ? Teacher(char* name){

? ? ? ? this->name = name;? ? ?

? ? ? ? cout << "Teacher有參構(gòu)造函數(shù)" << endl;

? ? }

? ? void setName(char* name){

? ? ? ? this->name = name;

? ? }

? ? char* getName(){

? ? ? ? return this->name;

? ? }

? ? //計數(shù),靜態(tài)函數(shù)

? ? static void count(){

? ? ? ? total++;? ? ? ?

? ? ? ? cout << total << endl;

? ? }

};

//靜態(tài)屬性初始化賦值

int Teacher::total = 9;

void main(){

? ? //靜態(tài)變量的使用

? ? Teacher::total++;

? ? cout << Teacher::total << endl;

? ? //靜態(tài)方法的使用一

? ? Teacher::count();

? ? //靜態(tài)方法的使用二

? ? Teacher t1("Hensen");

? ? t1.count();

}

4测蹲、常量對象和常函數(shù)

class Teacher{

private:

? ? char* name;

? ? int age;

public:

? ? Teacher(char* name,int age){

? ? ? ? this->name = name;

? ? ? ? this->age = age;

? ? ? ? cout << "Teacher有參構(gòu)造函數(shù)" << endl;

? ? }

? ? //常函數(shù)莹捡,當(dāng)前對象不能被修改,防止數(shù)據(jù)成員被非法訪問

? ? void myprint() const{

? ? ? ? //不能通過this->name修改值

? ? ? ? cout << this->name << "," << this->age << endl;

? ? }

? ? void myprint2(){? ? ? ?

? ? ? ? cout << this->name << "," << this->age << endl;? ?

? ? }

};

void main(){

? ? //普通對象

? ? Teacher t1("Hensen",20);

? ? //常對象

? ? const Teacher t2("rose", 18);

? ? //普通對象可以調(diào)用常函數(shù)扣甲,也可以調(diào)用普通函數(shù)

? ? t1.myprint();

? ? //t2.myprint2(); 常量對象只能調(diào)用常量函數(shù)篮赢,不能調(diào)用非常量函數(shù)

? ? t2.myprint();

}

虛函數(shù)

1、純虛函數(shù)(類似于抽象類)

當(dāng)一個類具有一個純虛函數(shù)琉挖,這個類就是抽象類

抽象類不能實例化對象

子類繼承抽象類启泣,必須要實現(xiàn)純虛函數(shù),如果沒有示辈,子類也是抽象類

class Shape{

public:

? ? //純虛函數(shù)

? ? virtual void sayArea() = 0;

? ? void print(){

? ? ? ? cout << "hi" << endl;

? ? }

};

class Circle : public Shape{

public:

? ? Circle(int r){

? ? ? ? this->r = r;

? ? }

? ? //必須實現(xiàn)純虛函數(shù)

? ? void sayArea(){

? ? ? ? cout << "圓的面積:" << (3.14 * r * r) << endl;

? ? }

private:

? ? int r;

};

void main(){

? ? Circle c(10);

}

2寥茫、接口

//接口(只是邏輯上的劃分,語法上跟抽象類的寫法沒有區(qū)別)

class Drawble{

? ? virtual void draw();

};

模板函數(shù)

1顽耳、模板函數(shù)使用坠敷,相當(dāng)于泛型

void myswap(int& a,int& b){

? ? int tmp = 0;

? ? tmp = a;

? ? a = b;

? ? b = tmp;

}

void myswap(char& a, char& b){

? ? char tmp = 0;

? ? tmp = a;

? ? a = b;

? ? b = tmp;

}

//可以將上面的函數(shù)抽取成模板函數(shù)

template <typename T>

void myswap(T& a, T& b){

? ? T tmp = 0;

? ? tmp = a;

? ? a = b;

? ? b = tmp;

}

void main(){

? ? int a = 10, b = 20;

? ? //使用時,根據(jù)實際類型射富,指定模板類型

? ? myswap<int>(a,b);

}

模板類

1膝迎、模板類使用

template<class T>

class A{

public:

? ? A(T a){

? ? ? ? this->a = a;

? ? }

protected:

? ? T a;

};

void main(){

? ? //實例化模板類對象

? ? A<int> a(6);

}

2、普通類繼承模板類

class B : public A<int>{

public:

? ? B(int a,int b) : A<int>(a){

? ? ? ? this->b = b;

? ? }

private:

? ? int b;

};

3胰耗、模板類繼承模板類

template <class T>

class C : public A<T>{

public:

? ? C(T c, T a) : A<T>(a){

? ? ? ? this->c = c;

? ? }

protected:

? ? T c;

};


構(gòu)造函數(shù)

函數(shù)分為三種

構(gòu)造函數(shù)

析構(gòu)函數(shù)

拷貝函數(shù)

1限次、無參構(gòu)造函數(shù)和有參構(gòu)造函數(shù)

class Teacher{

private:

? ? char *name;

? ? int age;

public:

? ? //無參構(gòu)造函數(shù)(無參構(gòu)造函數(shù)會覆蓋默認(rèn)的無參構(gòu)造函數(shù))

? ? Teacher(){

? ? ? ? cout << "無參構(gòu)造函數(shù)" << endl;

? ? }

? ? //有參構(gòu)造函數(shù)會覆蓋默認(rèn)的構(gòu)造函數(shù)

? ? Teacher(char *name, int age){

? ? ? ? this->name = name;

? ? ? ? this->age = age;

? ? ? ? cout << "有參構(gòu)造函數(shù)" << endl;

? ? }?

};

void main(){

? ? Teacher t1("Hensen",20);

? ? //另外一種調(diào)用方式

? ? Teacher t2 = Teacher("Hensen",21);

}

2、析構(gòu)函數(shù)

class Teacher{

private:

? ? char *name;

? ? int age;

public:

? ? //無參構(gòu)造函數(shù)賦默認(rèn)值

? ? Teacher(){

? ? ? ? this->name = (char*)malloc(100);

? ? ? ? strcpy(name,"Hensen");

? ? ? ? age = 20;

? ? ? ? cout << "無參構(gòu)造函數(shù)" << endl;

? ? }

? ? //析構(gòu)函數(shù)寫法

? ? //當(dāng)對象要被系統(tǒng)釋放時,析構(gòu)函數(shù)被調(diào)用卖漫,一般使用于程序的善后工作

? ? ~Teacher(){

? ? ? ? cout << "析構(gòu)" << endl;

? ? ? ? //釋放內(nèi)存

? ? ? ? free(this->name);

? ? }

};

void func(){

? ? Teacher t1;

}

void main(){

? ? func();

}

3费尽、拷貝構(gòu)造函數(shù)

class Teacher{

private:

? ? char *name;

? ? int age;

public:

? ? Teacher(char *name, int age){

? ? ? ? this->name = name;

? ? ? ? this->age = age;

? ? ? ? cout << "有參構(gòu)造函數(shù)" << endl;

? ? }

? ? //拷貝構(gòu)造函數(shù)寫法

? ? //默認(rèn)拷貝構(gòu)造函數(shù),就是值拷貝

? ? Teacher(const Teacher &obj){

? ? ? ? this->name = obj.name;

? ? ? ? this->age = obj.age;

? ? ? ? cout << "拷貝構(gòu)造函數(shù)" << endl;

? ? }

? ? void myprint(){

? ? ? ? cout << name << "," << age << endl;

? ? }

};

Teacher func1(Teacher t){

? ? t.myprint();

? ? return t;

}

void main(){

? ? Teacher t1("rose",20);

? ? func1(t1);

? ? //這里不會調(diào)用拷貝函數(shù)的

? ? //Teacher t1 ;

? ? //Teacher t2;

? ? //t1 = t2;

}

拷貝構(gòu)造函數(shù)被調(diào)用的場景:

聲明時賦值:Teacher t2 = t1;

作為參數(shù)傳入羊始,實參給形參賦值:上面的寫法就是

作為函數(shù)返回值返回旱幼,給變量初始化賦值:Teacher t3 = func1(t1);

4、拷貝函數(shù)的問題突委,淺拷貝(值拷貝)問題

class Teacher{

private:

? ? char *name;

? ? int age;

public:

? ? Teacher(char *name, int age){

? ? ? ? this->name = (char*)malloc(100);

? ? ? ? strcpy(this->name,name);

? ? ? ? this->age = age;

? ? ? ? cout << "有參構(gòu)造函數(shù)" << endl;

? ? }?

? ? ~Teacher(){

? ? ? ? cout << "析構(gòu)" << endl;

? ? ? ? //釋放內(nèi)存

? ? ? ? free(this->name);

? ? }

? ? void myprint(){

? ? ? ? cout << name << "," << age << endl;

? ? }

};

void func(){

? ? Teacher t1("rose", 20);

? ? Teacher t2 = t1;

}

void main(){

? ? func();

}

這樣的使用柏卤,會導(dǎo)致t1和t2都調(diào)用析構(gòu)函數(shù),導(dǎo)致同一份內(nèi)存被釋放兩次匀油,結(jié)果程序會報錯

5缘缚、解決淺拷貝問題,使用深拷貝

深拷貝很好理解敌蚜,其實就是將參數(shù)進(jìn)行再一次分配內(nèi)存桥滨,這樣的程序就不會出錯

class Teacher{

private:

? ? char *name;

? ? int age;

public:

? ? Teacher(char *name, int age){

? ? ? ? int len = strlen(name);

? ? ? ? this->name = (char*)malloc(len+1);

? ? ? ? strcpy(this->name, name);

? ? ? ? this->age = age;

? ? ? ? cout << "有參構(gòu)造函數(shù)" << endl;

? ? }

? ? ~Teacher(){

? ? ? ? cout << "析構(gòu)" << endl;

? ? ? ? //釋放內(nèi)存

? ? ? ? free(this->name);

? ? }

? ? //深拷貝

? ? Teacher(const Teacher &obj){

? ? ? ? int len = strlen(obj.name);

? ? ? ? this->name = (char*)malloc(len+1);

? ? ? ? strcpy(this->name,obj.name);

? ? ? ? this->age = obj.age;

? ? }

? ? void myprint(){

? ? ? ? cout << name << "," << age << endl;

? ? }

};

void func(){

? ? Teacher t1("rose", 20);

? ? Teacher t2 = t1;

}

void main(){

? ? func();

}

6、構(gòu)造函數(shù)初始化屬性寫法

class Student{

private:

? ? int id;

? ? //屬性對象可以直接的初始化

? ? //Teacher t = Teacher("miss cang");

? ? Teacher t1;

? ? Teacher t2;

public:

? ? //屬性對象可以在這里間接的初始化

? ? Student(int id,char *t1_n, char* t2_n) : t1(t1_n), t2(t2_n){

? ? ? ? this->id = id;

? ? ? ? cout << "Student有參構(gòu)造函數(shù)" << endl;

? ? }

? ? void myprint(){

? ? ? ? cout << id << "," << t1.getName() <<"," << t2.getName() << endl;

? ? }

? ? ~Student(){

? ? ? ? cout << "Student析構(gòu)函數(shù)" << endl;

? ? }

};

void func(){

? ? Student s1(10, "miss xu", "mrs li");

? ? Student s2(20, "miss ya", "mrs wang");

}

void main(){

? ? func();

}

7弛车、析構(gòu)函數(shù)和構(gòu)造函數(shù)的執(zhí)行順序

class Human{

public:

? ? Human(char* name, int age){

? ? ? ? this->name = name;

? ? ? ? this->age = age;

? ? ? ? cout << "Human 構(gòu)造函數(shù)" << endl;

? ? }

? ? ~Human(){

? ? ? ? cout << "Human 析構(gòu)函數(shù)" << endl;

? ? }

protected:

? ? char* name;

? ? int age;

};

class Man : public Human{

public:

? ? //給父類構(gòu)造函數(shù)傳參齐媒,同時給屬性對象賦值

? ? Man(char *brother, char *s_name, int s_age) : Human(s_name, s_age){

? ? ? ? this->brother = brother;

? ? ? ? cout << "Man 構(gòu)造函數(shù)" << endl;

? ? }

? ? ~Man(){

? ? ? ? cout << "Man 析構(gòu)函數(shù)" << endl;

? ? }

private:

? ? char* brother;

};

void func(){

? ? Man m1("Hensen", "HensenBoy", 18);

}

void main(){

? ? func();

}

輸出結(jié)果是:父類構(gòu)造函數(shù)先調(diào)用,子類的析構(gòu)函數(shù)先調(diào)用

Human構(gòu)造函數(shù)

Man構(gòu)造函數(shù)

Man析構(gòu)函數(shù)

Human析構(gòu)函數(shù)

友元函數(shù)

友元函數(shù):使得類的私有屬性可以通過友元函數(shù)進(jìn)行訪問

1帅韧、友元函數(shù)

class A{

? ? //友元函數(shù)聲明

? ? friend void modify_i(A *p, int a);

private:

? ? int i;

public:

? ? A(int i){

? ? ? ? this->i = i;

? ? }

? ? void myprint(){

? ? ? ? cout << i << endl;

? ? }?

};

//友元函數(shù)的實現(xiàn)

void modify_i(A *p, int a){

? ? p->i = a;

}

void main(){

? ? A* a = new A(10);

? ? a->myprint();

? ? modify_i(a,20);

? ? a->myprint();

}

2里初、友元類

class A{? ? ? ?

? ? //友元類聲明,表示B這個友元類可以訪問A類的任何成員

? ? friend class B;

private:

? ? int i;

public:

? ? A(int i){

? ? ? ? this->i = i;

? ? }

? ? void myprint(){

? ? ? ? cout << i << endl;

? ? }?

};

class B{

private:

? ? A a;

public:

? ? void accessAny(){

? ? ? ? a.i = 30;? ? ?

? ? }

};


類型轉(zhuǎn)換

C++類型轉(zhuǎn)換分為4種

static_cast:類型轉(zhuǎn)換忽舟,意圖明顯双妨,增加可閱讀性

const_cast:常量的轉(zhuǎn)換,將常量取出叮阅,并可以對常量進(jìn)行修改

dynamic_cast:子類類型轉(zhuǎn)為父類類型

reinterpret_cast:函數(shù)指針轉(zhuǎn)型刁品,不具備移植性

1、static_cast的使用

void* func(int type){?

? ? switch (type){

? ? ? ? case 1: {

? ? ? ? ? ? int i = 9;

? ? ? ? ? ? return &i;

? ? ? ? }

? ? ? ? case 2: {

? ? ? ? ? ? int a = 'X';

? ? ? ? ? ? return &a;

? ? ? ? }

? ? ? ? default:{

? ? ? ? ? ? return NULL;

? ? ? ? }

? ? }?

}

void func2(char* c_p){

? ? cout << *c_p << endl;

}

void main(){? ?

? ? int i = 8;

? ? double d = 9.5;

? ? i = static_cast<int>(d);

? ? //C的寫法

? ? //char* c_p = (char*)func(2);

? ? //C++的寫法

? ? char* c_p = static_cast<char*>(func(2));

? ? //C的寫法

? ? //func2((char*)(func(2)));

? ? //C++的寫法

? ? func2(static_cast<char*>(func(2)));

}

2浩姥、const_cast的使用

void func(const char c[]){

? ? //C的寫法

? ? //char* c_p = (char*)c;

? ? //c_p[1] = 'X';

? ? //C++的寫法挑随,提高了可讀性

? ? char* c_p = const_cast<char*>(c);

? ? c_p[1] = 'Y';

? ? cout << c << endl;

}

void main(){

? ? char c[] = "hello";

? ? func(c);

}

3、dynamic_cast的使用

class Person{

public:

? ? virtual void print(){

? ? ? ? cout << "人" << endl;

? ? }

};

class Man : public Person{

public:

? ? void print(){

? ? ? ? cout << "男人" << endl;

? ? }

? ? void chasing(){

? ? ? ? cout << "泡妞" << endl;

? ? }

};

class Woman : public Person{

public:

? ? void print(){

? ? ? ? cout << "女人" << endl;

? ? }

? ? void carebaby(){

? ? ? ? cout << "生孩子" << endl;

? ? }

};

void func(Person* obj){

? ? //C的寫法勒叠,C只會調(diào)用傳遞過來的對象方法兜挨,并不知道轉(zhuǎn)型失敗這回事

? ? //Man* m = (Man*)obj;

? ? //m->print();

? ? //C++的寫法,dynamic_cast如果轉(zhuǎn)型失敗眯分,會返回NULL拌汇,保證了代碼的安全性

? ? Man* m = dynamic_cast<Man*>(obj);?

? ? if (m != NULL){

? ? ? ? m->chasing();

? ? }

? ? Woman* w = dynamic_cast<Woman*>(obj);

? ? if (w != NULL){

? ? ? ? w->carebaby();

? ? }

}

void main(){

? ? Woman w1;

? ? Person *p1 = &w1;

? ? //輸出結(jié)果是生孩子

? ? func(p1);

}

4、reinterpret_cast的使用

void func1(){

? ? cout << "func1" << endl;

}

char* func2(){

? ? cout << "func2" << endl;

? ? return "abc";

}

typedef void(*f_p)();

void main(){

? ? //函數(shù)指針數(shù)組

? ? f_p f_array[6];

? ? f_array[0] = func1;

? ? //C的寫法

? ? //f_array[1] = (f_p)(func2);

? ? //C++方式

? ? f_array[1] = reinterpret_cast<f_p>(func2);

? ? //調(diào)用方法

? ? f_array[1]();

}

內(nèi)存分配

1弊决、C++ 通過new(delete)動態(tài)內(nèi)存分配

使用new的方式:和malloc一樣的功能噪舀,但是會自動調(diào)用構(gòu)造函數(shù)

使用delete的方式:和free一樣的功能魁淳,但是會自動調(diào)用析構(gòu)函數(shù)

指針的malloc、free可以和new与倡、delete互相摻雜使用界逛,但是malloc、free不會調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)

class Teacher{

private:

? ? char* name;

public:

? ? Teacher(char* name){

? ? ? ? this->name = name;

? ? ? ? cout << "Teacher有參構(gòu)造函數(shù)" << endl;

? ? }

? ? ~Teacher(){

? ? ? ? cout << "Teacher析構(gòu)函數(shù)" << endl;

? ? }

? ? void setName(char* name){

? ? ? ? this->name = name;

? ? }

? ? char* getName(){

? ? ? ? return this->name;

? ? }

};

void func(){

? ? Teacher *t1 = new Teacher("jack");

? ? cout << t1->getName() << endl;

? ? delete t1;

}

void main(){

? ? func();

}

運算符重載

1纺座、運算符重載的寫法一

class Point{

public:

? ? int x;

? ? int y;

public:

? ? Point(int x = 0, int y = 0){

? ? ? ? this->x = x;

? ? ? ? this->y = y;

? ? }

? ? void myprint(){

? ? ? ? cout << x << "," << y << endl;

? ? }

};

//重載+號

Point operator+(Point &p1, Point &p2){

? ? Point tmp(p1.x + p2.x, p1.y + p2.y);

? ? return tmp;

}

//重載-號

Point operator-(Point &p1, Point &p2){

? ? Point tmp(p1.x - p2.x, p1.y - p2.y);

? ? return tmp;

}

void main(){

? ? Point p1(10,20);

? ? Point p2(20,10);

? ? Point p3 = p1 + p2;

? ? //輸出結(jié)果30息拜,30

? ? p3.myprint();

}

2、運算符重載的寫法二

class Point{

public:

? ? int x;

? ? int y;

public:

? ? Point(int x = 0, int y = 0){

? ? ? ? this->x = x;

? ? ? ? this->y = y;

? ? }

? ? //成員函數(shù)比驻,運算符重載

? ? Point operator+(Point &p2){

? ? ? ? Point tmp(this->x + p2.x, this->y + p2.y);

? ? ? ? return tmp;

? ? }

? ? void myprint(){

? ? ? ? cout << x << "," << y << endl;

? ? }

};

void main(){

? ? Point p1(10, 20);

? ? Point p2(20, 10);

? ? //運算符的重載该溯,本質(zhì)還是函數(shù)調(diào)用

? ? //p1.operator+(p2)

? ? Point p3 = p1 + p2;

? ? p3.myprint();

}


3、通過友元函數(shù)和運算符重載訪問私有變量

class Point{

? ? friend Point operator+(Point &p1, Point &p2);

private:

? ? int x;

? ? int y;

public:

? ? Point(int x = 0, int y = 0){

? ? ? ? this->x = x;

? ? ? ? this->y = y;

? ? }?

? ? void myprint(){

? ? ? ? cout << x << "," << y << endl;

? ? }

};

Point operator+(Point &p1, Point &p2){

? ? Point tmp(p1.x + p2.x, p1.y + p2.y);

? ? return tmp;

}

void main(){

? ? Point p1(10, 20);

? ? Point p2(20, 10);

? ? //運算符的重載别惦,本質(zhì)還是函數(shù)調(diào)用

? ? //p1.operator+(p2)

? ? Point p3 = p1 + p2;

? ? p3.myprint();

}


其他

1、布爾類型(bool)

布爾類型的值大于0的都為true夫椭,布爾類型的值小于等于0的都為false

2掸掸、三目運算符

三目運算符可以作為參數(shù)進(jìn)行賦值

int a = 10, b = 20;

((a > b) ? a : b) = 30;

3、指針常量與常量指針

指針常量(int *const p):指針的常量蹭秋,表示不可以修改p的地址扰付,但是可以修改p的內(nèi)容

常量指針(const int *p):指向常量的指針,表示不可以修改p的內(nèi)容仁讨,但是可以修改p的地址

4羽莺、指針函數(shù)與函數(shù)指針

指針函數(shù)(int *fun(x,y)):指向指針的函數(shù),其實可以說是返回指針的函數(shù)

函數(shù)指針(int (*fun)(x,y);funa = fun;funb = fun;):指向函數(shù)的指針

加C/C++學(xué)習(xí)交流QQ群728483370洞豁,領(lǐng)取項目開發(fā)和新手教學(xué)等視頻

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盐固,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子丈挟,更是在濱河造成了極大的恐慌刁卜,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曙咽,死亡現(xiàn)場離奇詭異蛔趴,居然都是意外死亡,警方通過查閱死者的電腦和手機例朱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門孝情,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洒嗤,你說我怎么就攤上這事箫荡。” “怎么了烁竭?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵菲茬,是天一觀的道長。 經(jīng)常有香客問我,道長婉弹,這世上最難降的妖魔是什么睬魂? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮镀赌,結(jié)果婚禮上氯哮,老公的妹妹穿的比我還像新娘。我一直安慰自己商佛,他們只是感情好喉钢,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著良姆,像睡著了一般肠虽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上玛追,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天税课,我揣著相機與錄音,去河邊找鬼痊剖。 笑死韩玩,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的陆馁。 我是一名探鬼主播找颓,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼叮贩!你這毒婦竟也來了击狮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤妇汗,失蹤者是張志新(化名)和其女友劉穎帘不,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杨箭,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡寞焙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了互婿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捣郊。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖慈参,靈堂內(nèi)的尸體忽然破棺而出呛牲,到底是詐尸還是另有隱情,我是刑警寧澤驮配,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布娘扩,位于F島的核電站着茸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏琐旁。R本人自食惡果不足惜涮阔,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望灰殴。 院中可真熱鬧敬特,春花似錦、人聲如沸牺陶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掰伸。三九已至皱炉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碱工,已是汗流浹背娃承。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留怕篷,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓酗昼,卻偏偏與公主長得像廊谓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蒸痹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

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