面向對象複習提綱(一 類的基本知識)

參考網址:https://blog.csdn.net/zqixiao_09/article/details/51474556
參考網址:http://c.biancheng.net/cpp/biancheng/cpp/rumen/

1.類 class

類只是一個模板(Template),編譯後不佔用內存空間,所以在定義類時不能對成員變量進行初始化,因爲沒有地方存儲數據。只有在創建對象以後纔會給成員變量分配內存,這個時候就可以賦值了。

舉個栗子

class Student
{
public:
	Student();
	~Student();
private:
	string name='\0';//錯誤不能初始化
	int score;	
};

當成員函數定義在類外時,就必須在函數名前面加上類名予以限定。::被稱爲域解析符(也稱作用域運算符或作用域限定符),用來連接類名和函數名,指明當前函數屬於哪個類。
成員函數必須先在類體中作原型聲明,然後在類外定義,也就是說類體的位置應在函數定義之前。

2.構造函數

1.構造函數主要:用來初始化和內存分配
2.構造函數的調用是強制性的,一旦在類中定義了構造函數,那麼創建對象時就一定要調用,不調用是錯誤的。如果有多個重載的構造函數,那麼創建對象時提供的實參必須和其中的一個構造函數匹配;反過來說,創建對象時只有一個構造函數會被調用。

3.構造函數的一項重要功能是對成員變量進行初始化,爲了達到這個目的,可以在構造函數的函數體中對成員變量一一賦值,還可以採用參數初始化表

//採用參數初始化表
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ //TODO:}

注意,參數初始化順序與初始化表列出的變量的順序無關,它只與成員變量在類中聲明的順序有關。

舉個栗子

#include <iostream>
using namespace std;

class Demo{
private:
    int m_a;
    int m_b;
public:
    Demo(int b);
    void show();
};

Demo::Demo(int b): m_b(b), m_a(m_b){ }//-----------重點看這裏順序------//
void Demo::show(){ cout<<m_a<<", "<<m_b<<endl; }

int main(){
    Demo obj(100);
    obj.show();
    return 0;
}

3.析構函數

new 創建的對象位於堆區,通過 delete 刪除時纔會調用析構函數;如果沒有 delete,析構函數就不會被執行。(先構造着後析構

舉個栗子

#include <iostream>
#include <string>
using namespace std;

class Demo{
public:
    Demo(string s);
    ~Demo();
private:
    string m_s;
};
Demo::Demo(string s): m_s(s){ }
Demo::~Demo(){ cout<<m_s<<endl; }

void func(){
    //局部對象
    Demo obj1("1");
}

//全局對象
Demo obj2("2");

int main(){
    //局部對象
    Demo obj3("3");
    //new創建的對象
    Demo *pobj4 = new Demo("4");
    func();
    cout<<"main"<<endl;
    return 0;
}

這個問題是考試重點一定要了解變量的分配時期和表示的範圍
變化一下把25行的func()移動到24行或者26行後面,聰明的你能知道運行結果嗎?不知道耶沒有關係的哦,你可以試着運行一下哦,記住一個

祕訣就是先構造着後析構,加上變量生存期。

你就可以掌握了。

4.靜態成員 static

聰明的你知道什麼時候用靜態成員嗎?當這個類的所有公用一個變量或者函數最好用靜態成員,只花銷一個空間。看到這是不是還是很模糊,那麼給你舉個最簡單的例子,要統計計科182班的總成績或者總人數,不管哪個變量訪問總成績的時候都是一樣的。

和靜態成員變量類似,靜態成員函數在聲明時要加 static,在定義時不能加 static static函數是全域函數(global
functions),但是像一個指定class的對象成員一樣被調用。它們只能夠引用static
數據,永遠不能引用class的非靜態成員。它們也不能夠使用關鍵字this,因爲this實際引用了一個對象指針
,但這些
static函數卻不是任何object的成員,而是class的直接成員。

舉個栗子

#include <iostream>
using namespace std;

class Student{
public:
    Student(char *name, int age, float score);
    void show();
public:  //聲明靜態成員函數
    static int getTotal();
    static float getPoints();
private:
    static int m_total;  //總人數
    static float m_points;  //總成績
private:
    char *m_name;
    int m_age;
    float m_score;
};

int Student::m_total = 0;
float Student::m_points = 0.0;

Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
    m_total++;
    m_points += score;
}
void Student::show(){
    cout<<m_name<<"的年齡是"<<m_age<<",成績是"<<m_score<<endl;
}
//定義靜態成員函數
int Student::getTotal(){
    return m_total;
}
float Student::getPoints(){
    return m_points;
}

int main(){
    (new Student("小明", 15, 90.6)) -> show();
    (new Student("李磊", 16, 80.5)) -> show();
    (new Student("張華", 16, 99.0)) -> show();
    (new Student("王康", 14, 60.8)) -> show();

    int total = Student::getTotal();
    float points = Student::getPoints();
    cout<<"當前共有"<<total<<"名學生,總成績是"<<points<<",平均分是"<<points/total<<endl;

    return 0;
}

一個class的靜態數據成員也被稱作類變量"class variables",因爲它們的內容不依賴於某個對象,對同一個class的所有object具有相同的值。

例如,它可以被用作計算一個class聲明的objects的個數

舉個栗子

#include <iostream>
using namespace std;

class CDummy
{
public:
	static int n;
	CDummy () { n++; };
	~CDummy () { n--; };
};
int CDummy::n = 0;

int main ()
{
	CDummy a;
	CDummy b[5];
	CDummy * c = new CDummy;
	cout << a.n << endl;
	delete c;
	cout << CDummy::n << endl;
	return 0;
}

//上面代碼11行
int CDummy::n = 0;

初始化的時候才分配空間。

注意:static 成員變量的內存既不是在聲明類時分配,也不是在創建對象時分配,而是在(類外)初始化時分配。反過來說,沒有在類外初始化的
static 成員變量不能使用。
靜態成員函數與普通成員函數的根本區別在於:普通成員函數有 this
指針,可以訪問類中的任意成員;而靜態成員函數沒有 this 指針,只能訪問靜態成員(包括靜態成員變量和靜態成員函數)。

5.const成員變量

const 成員變量的用法和普通 const 變量的用法相似,只需要在聲明時加上 const 關鍵字。初始化 const 成員變量只有一種方法,就是通過參數初始化表
在這裏插入圖片描述

舉個栗子

#include<iostream>
using namespace std;
int main()
{
	//初始化列表必須放在構造函數的後面 
	char a[]="hello",b[]="world";
	char *p=a;
	cout<<p[2]<<endl;
	const char *p1=a;//數據不能改 
	p1=b;//可以修改指針
	//p1[2]='w';不可行,不行修改指針指向的數據
	cout<<p1[2]<<endl; 
	char *const p2=a;//指針不能移動
	p2[2]='s';
	//p2=b; 不可行
	cout<<p2[2]<<endl; 
	const char *const p3=a;
	//p3[2]='1';不可行 
	//p3=b;不可行 
	
}

const
離變量名近就是用來修飾指針變量的,離變量名遠就是用來修飾指針指向的數據,如果近的和遠的都有,那麼就同時修飾指針變量以及它指向的數據。

一旦將對象定義爲常對象之後,不管是哪種形式,該對象就只能訪問被 const 修飾的成員了(包括 const 成員變量和 const 成員函數),因爲非 const 成員可能會修改對象的數據(編譯器也會這樣假設),C++禁止這樣做。

舉個栗子

#include <iostream>
using namespace std;

class Student{
public:
    Student(char *name, int age, float score);
public:
    void show();
    char *getname() const;
    int getage() const;
    float getscore() const;
private:
    char *m_name;
    int m_age;
    float m_score;
};

Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(){
    cout<<m_name<<"的年齡是"<<m_age<<",成績是"<<m_score<<endl;
}
char * Student::getname() const{
    return m_name;
}
int Student::getage() const{
    return m_age;
}
float Student::getscore() const{
    return m_score;
}

int main(){
    const Student stu("小明", 15, 90.6);
    stu.show();  //error
    cout<<stu.getname()<<"的年齡是"<<stu.getage()<<",成績是"<<stu.getscore()<<endl;

    const Student *pstu = new Student("李磊", 16, 80.5);
    //pstu -> show();  //error
    cout<<pstu->getname()<<"的年齡是"<<pstu->getage()<<",成績是"<<pstu->getscore()<<endl;

    return 0;
}

6.友元函數friend

在這裏插入圖片描述

舉個栗子

#include <iostream>
using namespace std;

class Student{
public:
    Student(char *name, int age, float score);
public:
    friend void show(Student *pstu);  //將show()聲明爲友元函數
private:
    char *m_name;
    int m_age;
    float m_score;
};

Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }

//非成員函數
void show(Student *pstu){
    cout<<pstu->m_name<<"的年齡是 "<<pstu->m_age<<",成績是 "<<pstu->m_score<<endl;
}

int main(){
    Student stu("小明", 15, 90.6);
    show(&stu);  //調用友元函數
    Student *pstu = new Student("李磊", 16, 80.5);
    show(pstu);  //調用友元函數

    return 0;
}

舉個栗子

#include <iostream>
using namespace std;

class Address;  //提前聲明Address類

//聲明Student類
class Student{
public:
    Student(char *name, int age, float score);
public:
    void show(Address *addr);
private:
    char *m_name;
    int m_age;
    float m_score;
};

//聲明Address類
class Address{
private:
    char *m_province;  //省份
    char *m_city;  //城市
    char *m_district;  //區(市區)
public:
    Address(char *province, char *city, char *district);
    //將Student類中的成員函數show()聲明爲友元函數
    friend void Student::show(Address *addr);
};

//實現Student類
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
    cout<<m_name<<"的年齡是 "<<m_age<<",成績是 "<<m_score<<endl;
    cout<<"家庭住址:"<<addr->m_province<<"省"<<addr->m_city<<"市"<<addr->m_district<<"區"<<endl;
}

//實現Address類
Address::Address(char *province, char *city, char *district){
    m_province = province;
    m_city = city;
    m_district = district;
}

int main(){
    Student stu("小明", 16, 95.5f);
    Address addr("陝西", "西安", "雁塔");
    stu.show(&addr);
   
    Student *pstu = new Student("李磊", 16, 80.5);
    Address *paddr = new Address("河北", "衡水", "桃城");
    pstu -> show(paddr);

    return 0;
}

友元類
不僅可以將一個函數聲明爲一個類的“朋友”,還可以將整個類聲明爲另一個類的“朋友”,這就是友元類。友元類中的所有成員函數都是另外一個類的友元函數。
例如將類 B 聲明爲類 A 的友元類,那麼類 B 中的所有成員函數都是類 A 的友元函數,可以訪問類 A 的所有成員,包括
public、protected、private 屬性的。

在這裏插入圖片描述

下一篇博客鏈接:https://blog.csdn.net/weixin_43732535/article/details/106623681

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章