C++複習筆記

C++研究筆記


工程化

A.h

成員函數1;
成員函數2;


A.c

#include"A.h"

A::成員函數1{}
A::成員函數2{}

demo.c

#include"A.h"

int main()
{
  todo...
}

相比於C,C++的新特性

  • C++有布爾類型,C沒有哦…

初始化方法

  1. 複製初始化 int x = 1024; (C語言有的特性)
  2. 直接初始化 int x(1024);

隨用隨定義

  1. C語言:所有變量定義必須位於函數體的前面
  2. 隨用隨定義

輸入輸出方式

C

C++

  • 不用關心佔位符 ;譬如 %d ,%f …
  • 不用關心數據類型

    cout << oct|dec|hex|boolalpha << x <

OOP

數據的封裝

class Student
{
  public:
    void setAge(int _age){age = _age;}
    int getAge(){return age;}
  private:
    string name;
    int age;
}
  • 可以設置只讀屬性,類的封裝不設置對外寫接口

內聯函數

  • 類內定義的函數優先選擇編譯爲內聯函數

內聯函數

類外定義

  1. 同文件 類外定義 類名::成員{}
  2. 分文件類外定義 文件名 類名.h 調用者: #include”類名.h” 類名::成員{}

構造函數

  • 構造函數在對象實例化時被自動調用,且僅調用一次
  • 構造函數與類同名
  • 構造函數沒有返回值
  • 構造函數可以有多個重載形式
  • 實例化對象時僅用到一個構造函數
  • 當用戶沒有定義構造函數時,編譯器自動生成一個構造函數

初始化列表

student():m_strName("rose"),m_iAge(20){}
  • 初始化列表先於構造函數執行
  • 初始化列表只能用於構造函數

侯捷老師提到過推薦使用初始化列表

  • 初始化列表可以征服const聲明的常量,個人感覺就像先執行初始化列表,進行變量m_Age的初始化,然後const修飾將變量轉換成常量

    person(int age):m_Age(age){}

    private:
    const int m_Age;

拷貝構造函數

定義

類名(const 類名 &變量名)
  • 沒有定義拷貝構造函數,系統會自動生成一個默認的拷貝構造函數
  • 直接初始化,複製初始化,系統自動調用拷貝構造函數

整個對象的拷貝

析構函數

~類名(){}

對象數組

Coordinage coor[3] //棧實例化對象數組
coor[0].m_iX  //訪問成員

Coordinate *p = new Coordinate[3];  //堆實例化對象數組
p[0].m_iX  // p->m_iX 

p++;

P->m_iX;   // 第二個單元

深拷貝與淺拷貝

淺拷貝

*兩個實例化對象指向同一塊內存,最後操作的對象總是覆蓋掉前一對象的操作;釋放內存時,能夠導致內存的二次釋放

深拷貝

  1. 重新申請內存
  2. 傳入對象的內存賦值給新申請的內存,通常用遍歷的方式來賦值

Test(const Test& arr){

    m_pArr = new int[m_iCount];
    for(int i=0;i<m_iCount;i++)
    {
      m_pArr[i] = arr.m_pArr[i];
    }

}

對象指針

Coordinate *p = new Coordinate;

p->member;
(*p).member; //這個最是讓自己匪夷所思的,p指向了Obj,*p的意思就是讀取了Obj

#include <iostream>
using namespace std;
class Coordinate
{

public:
    Coordinate()
    {
    }
    // 打印座標的函數
    void printInfo()  
    {
        cout<<"("<<m_iX<<","<<m_iY<<")"<<endl;
    }
public:
    int m_iX;
    int m_iY;
};
int main(void)
{
    //定義對象數組
    Coordinate *coorArr = new Coordinate[2];
    coorArr[0].m_iX = 1;
    coorArr[0].m_iY = 2;
    coorArr[1].m_iX = 3;
    coorArr[1].m_iY = 4;


    //遍歷數組,打印對象信息
    for(int i = 0; i < 2; i++)
    {
        coorArr[i].printInfo();
    }   
    return 0;
}
  • 指針訪問對象數組成員:指針名[偏移量].成員

測試
1. &coorArr[0] 打印出來的結果是地址,coorArr[0]是一個數值嘛?
2. 測試結果,error,姑且就把它當作對象看待


對象成員指針

class Line
{
public:
    Line();
    ~Line();
private:
    Coordinate *m_pCoorA;
    Coordinate *m_pCoorB;
}

Line::Line()
{
    m_pCoorA = new Coordinate(1,3);
    m_pCoorB = new Coordinate(5,6);

}

Line::~Line()
{
    delete m_pCoorA;
    delete m_pCoorB;
}

對象成員指針

this指針

  • 解決參數與數據成員同名
  • this指針在參數列表中的位置

    return (*this) //返回一個對象

  • 返回引用對象,比如第一次操作改變了成員變量,第二次操作 返回對象.成員變量,變量會發生改變

  • 如果直接返回一個對象,第二次操作不會改變變量

this指針的特殊用法


#include<iostream>
using namespace std;

class Array
{
    public:
    Array(int len):m_len(len)
    {
        cout<<"構造函數"<<endl;
    }

    void set(int len)
    {
        m_len = len;
    }

    int get()
    {
        return m_len;
    }

    Array printinfo()
    {
        cout<<"m_len= "<<m_len<<endl;
        return (*this);
    }

    private:
    int m_len;
};

測試程序1

int main()
{
        Array arr1(10);
        arr1.printinfo().set(5);
        cout<<arr1.get()<<endl;
        return 0;
}
  • 測試結果arr1的數值沒有發生改變,因爲返回的另外一個對象,該對象爲臨時對象

解決方法

Array& printinfo()
{
    cout<<"m_len= "<<m_len<<endl;
    return (*this);
}
  • 將返回對象修改爲返回引用,指向同一個內存區域,就可以測試成功

返回對象修改爲對象指針

Array* printinfo()
{
    cout<<"m_len= "<<m_len<<endl;
    return this;
}

int main()
{
        Array arr1(10);
        arr1.printinfo()->set(5);
        cout<<arr1.get()<<endl;
        return 0;
}

const

  1. const int * p = int const *p

const修飾的是(*p) , 即指針指向的數值,數值爲常量

  1. int * const p

const修飾的是p, 指針爲常量

  1. int x=3 const int &y = x x=0正確,y=20錯誤(const修飾了引用y,y爲常量,不可以賦值)

  2. int x =3 (變量) const int x= 3 (常量)

    • 如果成員變量前const修飾,那麼構造函數在函數體內定義,這樣的方法會產生error;但是倘若使用初始化列表的方法的話,程序會成功,初始化列表完成了成員變量的初始化,然後const修飾,之後成員變量爲常量,不可進行賦值操作了.
    • 常對象成員,也可以用初始化列表這樣的技術手段

常成員函數

函數 const;

  • 常成員函數中不能改變成員變量的數值

    void change() const
    {
    m_iX = 10;
    }

    void change(const *this)
    {
    this->m_iX = 10; //error const修飾了(*p)指向的數值,數值爲常量
    }

    //互爲重載
    void changeX() const;
    void changeX();

  • 調用的時候需要前面const來區分,否則調用普通函數,而不是常成員函數

  • 常成員函數的本質是內部使用常this指針
  • 常成員函數內不能調用普通的成員函數

常指針與常引用

int main(void)
{
    Coordinate coor1(3,5);
    const Coordinate &coor2 = coor1;
    const Coordinate *pCoor3 = &coor1;

    coor1.printInfo();
    coor2.getX();  //error getX()要求傳入讀寫權限的參數,而coor2傳入的this指針只有讀權限   
    pCoor3->getY(); //error ...同上
    return 0;
}
  • getX, getY爲普通成員函數,有着讀寫權限.
發佈了187 篇原創文章 · 獲贊 3 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章