第十章-對象和類

C++中,類由兩部分組成:
1、類聲明。包括成員變量和成員函數。一般方法在頭文件中。
2、類方法定義。包括成員函數的定義。一般放在實現源代碼中。
控制訪問中有有兩個關鍵字:private和public
直接上圖:
這裏寫圖片描述
類對象可以直接訪問public成員 ,而private成員只能通過public方法來訪問。
private是可選的,因爲不寫的話,默認就是private。
類默認訪問類型是private,而結構默認訪問類型是public。

實現成員函數:
1、定義成員函數時,使用作用域解析符::來標示函數所屬的類。
2、類方法可以訪問類的private組件。

內聯方法:其定義位於類聲明中的函數都將自動成爲內聯函數,類聲明常將短小的成員函數作爲內聯函數。寫進頭文件中。

10.3構造函數和析構函數。
構造函數和析構函數定義時,也必須加類作用域
爲區分構造函數參數名和類成員名,一般有兩種做法:
1、類成員名前加m_前綴
2、類成員名後加_後綴
構造函數是用來創建對象的,不能通過對象調用!因爲在構造函數構造出對象之前,對象不存在。

默認構造函數:
在用戶沒有提供任何構造函數時,C++提供一個默認構造函數:Stock::Stock();
如果提供了自定義的構造函數,很奇怪,這個默認構造函數就不提供了,想用的話,就必須自己敲上。
自己敲默認構造函數有兩種方式,一種就是像默認的那樣,手敲一個就好了。另一種就是給自定義的構造函數的所有參數提供默認值。
一開始感覺提供默認值是個不錯的方法,能少寫東西,後來發現,還是老老實實的把默認構造函數敲出來,瞅着順眼一些。

析構函數沒有返回值(連void都沒有),也沒有參數,在其類名稱前加~就好了!

放一段類聲明、類定義和類使用的代碼:

//student.h

#ifndef STUDENT_H_
#define STUDENT_H_

#include<string>
class Student
{
private:
    std::string name_;
    int age_;
public:
    Student();
    Student(std::string name, int age);
    ~Student();
    void show();
};

#endif
//student.cpp
#include<iostream>
#include"student.h"

Student::Student()
{
    name_ = "NULL";
    age_ = 0;
}

Student::Student(std::string name, int age)
{
    name_ = name;
    age_ = age;
}

Student::~Student()
{
}

void Student::show()
{
    std::cout<<"name: "<<name_<<"age: "<<age_<<std::endl;
}
//using cpp
int main
{
...
Student james; //調用默認構造函數。
Student kobe("kobe", 32);//調用自定義構造函數。
james.age;//不允許的。因爲爲private。
kobe.show();//這是可以的,調用public成員函數。
...
}

在初始化部分,說一下C++11的列表初始化。就是大括號{}的應用,如下幾種都是可以的:

Student james{};
Student kobe{"kobe", 30};
Student jordan = {"jordan", 40};

const成員函數:
先看一段代碼:

const Student kobe("kobe", 32);
kobe.show();//這句會報錯,因爲編譯器懷疑show()方法將會對kobe對象做更改,而kobe又是const的。

解決方法就是,成員函數在不修改類對象的情況的下,在聲明和定義時在函數後添加const:

//類方法聲明中:
void show() const;
//函數定義中:
void Student show() const
{...}

this指針:
先說來源:
假如我定義了一個成員函數,這個函數涉及到兩個對象,此時就有用了。舉個簡單栗子。Student比較兩個對象的年齡,返回年齡低的那個對象。

//student.h

#ifndef STUDENT_H_
#define STUDENT_H_

#include<string>
class Student
{
private:
    std::string name_;
    int age_;
public:
    Student();
    Student(std::string name, int age);
    ~Student();
    void show();
    const Student& older(const Student& s) cosnt;//比較年齡方法函數。
};

#endif
//student.cpp
#include<iostream>
#include"student.h"

...
const Student& older(const Student& s) cosnt
{
    if(s.age > age)
        return s;
    else
        return *this;
}

說一下成員函數中的三個const。
這個成員函數調用了兩個對象:
一個是參數列表中的s,爲顯式調用,因爲直接寫出來了。
另外一個就是本身對象,爲隱式調用,因爲它用到了本身對象的age成員。
參數列表中的const表示不會改動顯式調用的s對象。
函數後方的const表示不會改動隱式調用的對象,也就是本身對象。
函數返回值的const表示返回的是const類型對象,因爲是引用,所以返回對象肯定在s和本身對象之間,這倆都是const,所以返回類型也是const。

再說一下this,this是指針,指向用來調用成員函數的對象。也就是指向對象本身。
由於是指針,所以*this爲解引用後的對象。而調用對象成員和方法的話要用->

使用如下:

//main.cpp
Student older;
older = kobe.older(james);//這兩種方式都可以。
older = james.older(kobe);//這兩種方式都可以。

對象數組。只說一句:要創建類對象數組,類必須要有默認構造函數。

類作用域:
在類中定義的名稱(數據成員或函數成員)的作用域爲整個類。在類中已知,類外未知。類作用域意味着不能從外部直接訪問類的成員,也就是說,要調用成員數據或者成員方法,必須通過對象。

kobe.show();//這樣是可以的。
show();//直接這樣不對!

總之,在類聲明中,可以什麼都不加。在類定義中,需要加類作用域。在調用時,必須通過對象。構造函數也不例外,因爲它用於對象創建。

關於類成員初始化這塊,比較繞,單開一篇寫一寫。

作用域內枚舉在這種情況下出現:

enum egg {small, medium, large};
enum t-shirt {small, medium, large};//尷尬了,兩個枚舉,同樣的名字。。

在枚舉名前加上class即可:

enum class egg {small, medium, large};
enum class t-shirt {small, medium, large};

用的時候,加上枚舉名限定枚舉量就可以了;

egg choice = egg::small;
t_shirt Floyd = t_shirt::large;

10.7的抽象數據類型,深層次是數據結構和STL相關的東西,所以後續再說。這裏只需要知道,這裏它定義的類不是具體的類了,不像Student這種非常具體的類,而是一個抽象的容器,然後用類實現,搞出來一個容器類,用這個類去對數據進行存儲和操作。

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