1. 程式人生 > >C++類和物件詳解(new與不new的區別)

C++類和物件詳解(new與不new的區別)

一、"類" 的介紹

    在C++中, 用 "類" 來描述"物件", 所謂的"物件"是指現實世界中的一切事物。那麼類就可以看做是對相似事物的抽象, 找到這些不同事物間的共同點, 如自行車和摩托車, 首先他們都屬於"物件", 並且具有一定得相同點, 和一些不同點, 相同點如他們都有質量、都有兩個輪子, 都是屬於交通工具等。"都有質量"、"兩個輪子"屬於這個物件的屬性, 而"都能夠當做交通工具"屬於該物件具有的行為, 也稱方法。

    類是屬於使用者自定義的資料型別, 並且該型別的資料具有一定的行為能力, 也就是類中說描述的方法。通常來說, 一個類的定義包含兩部分的內容, 一是該類的屬性, 另一部分是它所擁有的方法。以 "人類" 這個類來說, 每個人都有自己的姓名、年齡、出生日期、體重等, 為 人類 的屬性部分, 此外, 人能夠吃飯、睡覺、行走、說話等屬於人類所具有的行為。

    上面舉例中所描述的 "人" 類僅僅是具有人這種物件的最基礎的一些屬性和行為, 可以稱之為人的"基類"。 再說說一些具有一些職業的人, 例如學生, 一個學生還具有"基類"中所沒有的屬性, 如學校、班級、學號; 也可以具有基類所不具有的行為, 如每天需要去上課, 需要考試等。

    學生類可以看做是基類的一個擴充套件, 因為他具有基類的所有屬性和行為, 並且在此基礎上增加了一些基類所沒有的屬性和行為, 像"學生"這樣的類稱為"人類"這個基類的"派生類"或者"子類"。在學生的基礎上海可以進一步的擴展出其他更高階的類, 如"研究生"類。

到此, 我們不再更深的去介紹類的其他相關知識。

二:類的使用

類是建立物件的模板,一個類可以建立多個物件,每個物件都是類型別的一個變數;建立物件的過程也叫類的例項化。每個物件都是類的一個具體例項(Instance),擁有類的成員變數和成員函式。
   與結構體一樣,類只是一種複雜資料型別的宣告,不佔用記憶體空間。而物件是類這種資料型別的一個變數,佔用記憶體空間。

類的宣告

類是使用者自定義的型別,如果程式中要用到類,必須先進行宣告,或者使用已存在的類(別人寫好的類、標準庫中的類等),C++語法本身並不提供現成的類的名稱、結構和內容。
一個簡單的類的定義:

class Stock { //class declaration

private:  //預設使用關鍵字private

      std::stringcompany;

      longshares;

      doubleshare_val;

      doubletotal_val;

      voidset_tot() { total_val = shares * share_val; } //類中宣告的函式自動成為行內函數

      //voidset_tot(); //defination kept separate

public:

      Stock();

      Stock(conststd::string &co, long n, double pr);

      ~Stock();

      voidacquire(const std::string &co, long n, double pr);

      voidbuy(long num, double price);

      voidsell(long num, double price);

      voidupdate(double price);

      voidshow() const; //promises not to change invoking object

}; //note semicolon at the end

該例建立了一個Stock類,它包含了4個成員變數。
class是C++中的關鍵字,用於宣告一個類;緊接 class 關鍵字之後的是我們自定義的類名 Stock;由{ }包圍的是類體。宣告類時不能對成員變數進行初始化,只有在建立物件以後才能賦值。
    類可以理解為一種新的資料型別,該資料型別的名稱是 Stock。與 char、int、float 等基本資料型別不同的是,Student 是一種複雜資料型別,可以包含基本型別,而且多了很多基本型別中沒有的特性。

需要注意的是:在類宣告的最後有一個分號(;),它是類宣告的一部分,表示類宣告結束了,不能省略。

建立物件

聲明瞭Stock 資料型別之後,就可以用它來定義變量了,如:

Stock s1  //建立物件

該語句聲明瞭一個名字為 s1、資料型別為 Stock 的變數。這和:

int a;  //定義整形變數

語句定義了一個整型變量表達的意思是類似的。而 s1 這個變數我們稱之為 Student 類的物件。

在定義類的物件時,class 關鍵字可要可不要。但出於習慣我們通常都會省略掉class關鍵字,例如:

1.        class Stock s1;  //正確

2.        Stock s1;  //同樣正確

建立類的物件時,除了能定義單個變數以外,還可以定義一個數組或者指標。例如:

1.        Stock all_stock[100];

2.        Stock *pointer;

第一條語句定義了一個 all_stock 陣列,該資料擁有100個元素,每個元素都是 Stock 型別。第二條語句定義了一個 Stock 型別的指標 pointer,該指標可以指向 Stock 型別的變數(物件),用法和普通指標一樣。

宣告類的同時建立物件

和結構體(struct)類似,你可以先宣告類,然後再建立物件,也可以在宣告類的同時建立物件。如下所示:

class Person{

public:

//成員變數

char *name;

int age;

double weight;

//成員函式

void say(){

std::cout << "我是" << name << ",今年" << age << "歲,體重" << weight << std::endl;

}

}p1, p2;

這個時候你也可以省略類名,直接建立物件。

直接定義物件,在C++中是合法的、允許的,但卻很少用,也不提倡用。
一個完整的示例:

標頭檔案:person.h

#ifndef PERSON_H_

#define PERSON_H_

class Person {

public:

      //成員變數

      char*name;

      intage;

      doubleweight;

      //成員函式

      voidsay() {

         std::cout << "我是" << name <<",今年" << age<< "歲,體重" << weight <<std::endl;

      }

};

#endif  PERSON_H_

原始檔main.cpp

#include <iostream>

#include "person.h";

int main() {

       //建立物件

       Person p1;

       p1.name ="張三";

       p1.age = 25;

       p1.weight =60.00;

       p1.say();

       //定義指標

       Person *p2 =&p1;

       p2->name ="李四";

       p2->age =50;

       p2->weight= 68.94;

       p2->say();

       system("pause");

       return 0;

}

執行結果:


public 是C++中的關鍵字,用來修飾成員變數和成員函式,表示它們是公有的。只有 public 後面的成員變數和成員函式才能被建立的物件訪問到,沒有使用 public,那麼建立物件後就不能使用任何成員。

main 函式中首先建立了一個物件 p1,然後又定義了一個Person 型別的指標變數。可以發現,和結構體(struct)類似,一個物件通過成員選擇符”.“來訪問成員變數和成員函式,而指標變數通過指標操作符”->“來訪問成員。

注意:物件指標指向的是一個具體的物件,而不是類。下面的寫法是錯誤的:
Person *p1;

p1 = &Person;

物件的作用域、可見域與生存週期

類物件的作用域、可見域以及生存週期與普通變數的保持相同, 當物件生存週期結束時物件被自動撤銷, 所佔用的記憶體被回收, 需要注意的是, 如果物件的成員函式中有使用 new 或者 malloc申請的動態記憶體程式不會對其進行釋放, 需要我們手動進行清理, 否則會造成記憶體洩露。

C++用new和不用new建立物件區別

起初剛學C++時,很不習慣用new,後來看老外的程式,發現幾乎都是使用new,想一想區別也不是太大,但是在大一點的專案設計中,有時候不使用new的確會帶來很多問題。當然這都是跟new的用法有關的。new建立物件,使用完後需使用delete刪除,跟申請記憶體類似。所以,new有時候又不太適合,比如在頻繁呼叫場合,使用區域性new物件就不是個好選擇,使用全域性類物件或一個經過初始化的全域性類指標似乎更加高效。

一、new建立類物件與不new區別

下面是自己總結的一些關於new建立物件特點:

new建立物件需要指標接收,一處初始化,多處使用

new建立物件使用完需delete銷燬

new建立物件直接使用堆空間,而區域性不用new定義物件則使用棧空間

new物件指標用途廣泛,比如作為函式返回值、函式引數等

頻繁呼叫場合並不適合new,就像new申請和釋放記憶體一樣

二、new建立類物件例項

1、new建立物件例子:

CTest*  pTest = new  CTest();

delete pTest;

pTest用來接收物件指標。

不用new,直接使用類定義申明:

CTest  mTest;

此種建立方式,使用完後不需要手動釋放,該類解構函式會自動執行。而new申請的物件,則只有呼叫到delete時再會執行解構函式,如果程式退出而沒有執行delete則會造成記憶體洩漏。

2、只定義類指標

這跟不用new申明物件有很大區別,類指標可以先行定義,但類指標只是個通用指標,在new之前並不為該類物件分配任何記憶體空間。比如:

CTest*  pTest = NULL;

   但使用普通方式建立的類物件,在建立之初就已經分配了記憶體空間。而類指標,如果未經過物件初始化,則不需要delete釋放。

3、new物件指標作為函式引數和返回值

下面是隨手寫一個例子,不太嚴謹。主要示意一下類指標物件作為返回值和引數使用。

#include<iostream>

using namespacestd;

class TestA {

public:

       int a;

       TestA() {

         cout << "TestA的預設建構函式" <<endl;

       }

       ~TestA() {

         cout << "TestA的解構函式" <<endl;

       }

};

class TestB {

public:

       int b;

       TestB() {

         cout << "TestB的預設建構函式" <<endl;

       }

       ~TestB() {

         cout << "TestB的解構函式" <<endl;

       }

};

TestA* fun(TestB*pb) {

   TestA* pa = new TestA();

   pa->a = pb->b;

   return pa;

}

int main() {

       TestA* pa = new TestA();

       TestB* pb = new TestB();

       pb->b = 20;

       TestA* pRes = fun(pb);

       if(pa != NULL) {

         delete pa;

       }

       if(pb != NULL) {

         delete pb;

       }

       if(pRes != NULL) {

         delete pRes;

       }

       system("pause");

       return 0;

}

結果: