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;
}
結果: