宣告和定義建構式
建構式:專門用于構造新物件、將值賦給它們的資料成員,在創建類物件時被呼叫,
建構式特征:
- 建構式的名稱和類名相同
- 建構式可以多載
- 建構式沒有宣告型別
由于Stock物件提供3個值,因此應為建構式提供3個引數,
Stock(const string &co, long n = 0, double pr = 0.0)
第一個引數:指向字串的指標,用于初始化成員company,n和pr引數為shares和share_val成員提供值,
注意:沒有回傳值,原型位于類宣告的公共部分,
Stock::Stock(const string &co, long n, double pr)
{
company = co;
if(n < 0)
{
cout << "Number of shares can't be negative;"
<< company << " shares set to 0.\n";
shares = 0;
}
else
shares = 0;
share_val = pr;
set_tot();
}
上述代碼與acquire()函式相同,區別在于,程式宣告物件時,將自動呼叫建構式,
為了避免函式引數名與成員名相同,在資料成員名中使用m_前綴:m_company
使用建構式
- 顯示呼叫建構式
Stock food = Stock("World Cabbage", 250, 1.25);
- 隱式呼叫建構式
Stock garment("Furry Mason", 50, 2.5);
- 建構式與new
每次創建類物件(甚至使用new動態分配記憶體)時,都會使用建構式
Stock *pstock = new Stock("Electroshock Games", 18, 19.0);
建構式是用來創建物件,不能通過物件來呼叫,
默認建構式
默認建構式是在未提供顯式初始值時,用來創建物件的建構式,默認建構式沒有引數,因為宣告中不包含值,
Stock fluffy_the_cat;
注意:如果沒有提供任何建構式,則C++將自動提供默認建構式,
如果為類定義了建構式,則程式員必須為它提供默認建構式,
定義默認建構式:
- 一種是給已有建構式的所有引數提供默認值,
Stock(const string &co = "Error", int n = 0, double pr = 0.0);
- 通過函式多載來定義另一個建構式,即一個沒有引數的建構式,
Stock();
注意:默認建構式只能有一個,通常使用第一種來作為默認建構式,
創建了默認建構式后,就可以宣告物件,而不對它們進行顯示初始化,
解構式
解構式:用建構式創建物件后,程式負責跟蹤該物件,直到過期為止,物件過期時,程式將自動呼叫一個特殊的成員函式,即解構式,
如果建構式使用new來分配,則解構式將使用delete來釋放記憶體,
如果沒有使用new,則需要隱式解構式,
宣告解構式,在類名前加上~:
~Stock();
解構式沒有引數,沒有回傳值,沒有宣告型別,
每個類都只能有一個解構式,
解構式不承擔重要的作業,因此可以將它撰寫為不執行任何操作的函式
Stock::~Stock()
{
}
解構式的呼叫:
- 如果創建的是靜態存盤類物件,則其解構式將在程式結束時自動被呼叫
- 如果創建的是自動存盤類物件,則其解構式將在程式執行完代碼塊時自動被呼叫
- 如果物件是通過new創建的,則它將駐留在堆疊記憶體或者自由存盤區,當使用delete來釋放記憶體時,則其解構式將自動被呼叫,
- 程式可以創建臨時物件來完成特定的操作,在這種情況下,程式將在結束對該物件的使用時自動呼叫其解構式,
- 在類物件過期時解構式將自動呼叫,因此必須有一解構式,
- 如果程式員沒有提供解構式,編譯器會隱式宣告一個默認解構式,并發現導致物件被洗掉的代碼后,提供默認解構式,
- 最先創建的物件將最后洗掉,即最后呼叫解構式
股票改進
//stock10.h
#ifndef STOCK10_H
#define STOCK10_H
#include <string>
class Stock
{
private:
string company;
long shares;
double share_val;
double total_val;
void set_tot(){total_val = shares * share_val;}
public:
Stock();
Stock(const string &co, long n = 0, double pr = 0.0);
~Stock();
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};
#endif
//stock10.cpp
#include <iostream>
#include "stock10.h"
//默認建構式
Stock::Stock()
{
cout << "Default constructor called\n";
company = "no name";
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
//建構式
Stock::Stock(const string &co, long n, double pr)
{
cout << "Constructor using" << co << " called\n";
company = co;
if(n < 0)
{
cout << "Number of shares can't be negative; "
<< company << " shares set to 0.\n";
shares = 0;
}
else
shares = n;
share_val = pr;
set_tot();
}
//解構式
Stock::~Stock()
{
cout << "Bye, " << company << "!\n";
}
void Stock::buy(long num, double price)
{
if(num < 0)
{
cout << "Number of shares purchased can't be negative. "
<< "Transaction is aborted.\n";
}
else
{
shares += num;
share_val = price;
set_tot();
}
}
void Stock::sell(long num, double price)
{
if(num < 0)
{
cout << "Number of shares sold can't be negative. "
<< "Transaction is aborted.\n";
}
else if(num > shares)
{
cout << "You can't sell more than you have! "
<< "Transaction is aborted.\n";
}
else
{
shares -= num;
share_val = price;
set_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
void Stock::show()
{
cout << "Company:" << company
<<" Shares:" << shares << '\n'
<<" Share Price:$" << share_val
<<" Total Worth:$" << total_val << '\n';
}
//usestok1.cpp
#include <iostream>
#include "stock10.h"
int main()
{
//添加這兩大括號,兩個解構式呼叫將在到達回傳陳述句前執行
//如果沒有這些大括號,將執行完整個main()后,才呼叫解構式,即在兩個解構式呼叫前關閉則無法看到最后兩條訊息
{
cout << "Using constructors to create new objects\n";
Stock stock1("NanoSmart", 12, 20.0);
stock1.show();
Stock stock2 = Stock("Boffo Objects", 2, 2.0);
stock2.show();
cout << "Assigning stock1 to stock2:\n";
//將一個物件賦給同型別的另一個物件,其源物件的每個資料成員的內容復制到目標物件中相應的資料成員中
stock2 = stock1;
cout << "Listing stock1 and stock2:\n";
stock1.show();
stock2.show();
cout << "Using a constructor to reset an object\n";
//將新值賦給它,建構式創建一個新的、臨時的物件,然后賦值給stock1.隨后程式呼叫解構式,以洗掉該臨時物件
stock1 = Stock("Nifty Foods", 10, 50.0);
cout << "Revised stock1:\n";
stock1.show();
cout << "Done\n";
}
return 0;
}
Using constructors to create new objects
//stock1
Constructor using NanoSmart called
Company:NanoSamrt Shares:12
Share Price:$20.00 Total Worth:$240.00
//stock2
Constructor using Boffo Objects called
Company:Boffo Objects Shares:2
Share Price:$2.00 Total Worth:$4.00
Assigning stock1 to stock2:
Listing stock1 and stock2:
Company:NanoSamrt Shares:12
Share Price:$20.00 Total Worth:$240.00
Company:NanoSamrt Shares:12
Share Price:$20.00 Total Worth:$240.00
Using a constructor to reset an object
Constructor using Nifty Foods called
Bye, Nifty Food;
Revised stock1;
Company:Nifty Foods Shares:10
Share Price:$50.00 Total Worth:$500.00
Done
//main()函式結束時,其區域變數(stock1和stock2)將消失,由于這種自動變數被放在堆疊中,因此最后創建的物件將最先被洗掉,最先創建的物件將最后被洗掉("NanoSmart"最初位于stock1中,但隨后被傳輸到stock2中,然后stock1被重置為"Nifty Food"),
Bye, NanoSmart!
Bye, Nifty Foods!
下面兩條陳述句根本性差別:
//第一條是初始化,它創建有指定值的物件,可能會創建臨時物件(也有可能不會)
Stock stock2 = Stock("Boffo Objects", 2, 2.0);
//第二條是賦值,像這樣在賦值陳述句中使用建構式總會導致在賦值前創建一個臨時物件,
stock1 = Stock("Nifty Foods", 10, 50.0);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/236147.html
標籤:其他
