我們經常會看到一個類中可能會出現另一個類的對象作為它的數據成員,既然是對象,那麼就會涉及到這個對象成員要初始化的問題。而程序中各種數據的共享,在一定程度上破環了數據的安全性。C++中有什麼方法可以保證數據共享又防止數據改動。另外除以上兩個問題,我還將說說C++的多文件程序。
1.我們在創建類的對象時,如果這個類具有內嵌的對象,那麼該對象成員也將被自動創建。所以創建對象時既要對本類的基本數據成員初始化,又要對內嵌的對象初始化。具體怎麼做呢,我還是用Employee(雇員)和Salary(薪水)兩個類來舉個實例:
1 #include "stdafx.h"
2 #include<string>
3 #include<iostream>
4
5 class Employee
6 {
7 private:
8 std::string id;
9 std::string name;
10 public:
11 Employee(std::string id,std::string name);
12 ~Employee();
13 void showEmployee();
14 };
15
16 Employee::Employee(std::string id,std::string name):id(id),name(name)
17 {
18 std::cout<<"構造對象employee"<<std::endl;
19 }
20
21 Employee::~Employee()
22 {
23 std::cout<<"釋放對象employee內存空間"<<std::endl;
24 }
25
26 void Employee::showEmployee()
27 {
28 std::cout<<"編號:"<<id<<std::endl;
29 std::cout<<"姓名:"<<name<<std::endl;
30 }
31
32
33 class Salary
34 {
35 private:
36 Employee employee; //雇員
37 double wage;//工資
38 double bonus;//獎金
39 double commission;//提成
40 double allowance;//津貼
41 double subsidy;//補貼
42 public:
43 Salary(double wage,double bonus,double commission,double allowance,double subsidy,std::string id,std::string name);
44 ~Salary();
45 void showSalary();
46 };
47
48 Salary::Salary(double wage,double bonus,double commission,double allowance,double subsidy,std::string id,std::string name):wage(wage),bonus(bonus),commission(commission),allowance(allowance),subsidy(subsidy),employee(id,name)//初始化對象成員employee
49 {
50 std::cout<<"構造對象salary"<<std::endl;
51 }
52
53 Salary::~Salary()
54 {
55 std::cout<<"釋放對象salary內存空間"<<std::endl;
56 }
57
58 void Salary::showSalary()
59 {
60 employee.showEmployee();//顯示雇員信息
61 std::cout<<"薪水:"<<std::endl;
62 std::cout<<" 工資:"<<wage<<std::endl;
63 std::cout<<" 獎金:"<<bonus<<std::endl;
64 std::cout<<" 提成:"<<commission<<std::endl;
65 std::cout<<" 補貼:"<<subsidy<<std::endl;
66 std::cout<<" 津貼:"<<allowance<<std::endl;
67 }
68
69
70 int main()
71 {
72 {
73 Salary salary(3000,3000,0,200,100,"001","aaa");
74 salary.showSalary();
75 }
76
77 return 0;
78 }
結果:
從初始化成員對象的代碼中可以看到其實和之前所說的成員初始化表對數據成員初始化的形式是一樣的。看到main函數體裡的實現部分,可能有人會問那個大括號是否畫蛇添足了。如果單單是從程序運行的流程考慮,的確沒什麼必要。而我特意加上這個大括號是為了說明在系統編譯運行時它的順序是怎麼樣的,從顯示的結果來看,是先調用了Employee()的構造函數,在調用自己(Salary())的構造函數,而在調用各自的析構函數時則剛好相反。也許有人會問,那如果Salary裡的對象成員不只一個,那麼這些對象成員的構造函數調用的順序是怎麼樣的?其實系統編譯運行時對對象成員的構造函數調用的順序是根據其在類聲明中的順序來依次調用,而釋放對象空間(析構函數)的過程則剛好相反;
2.C++的常類型的引入,就是為了既保證數據共享又防止數據被改動。在面向對象裡常類型主要有常對象、常數據成員以及常成員函數。(1)常對象的形式有:類名const 對象名[參數表]或const 類名 對象名[參數表],常對象中的數據成員值在對象的整個對象的生存期內不能被改變,而且常對象不能調用普通成員函數,只能調用常成員函數。(2)常數據成員的形式其實和C++對C語言的非面向對象特性擴充(1)所講到過的常量是一樣,但要注意的是類裡的常數據成員只能通過初始化列表對其進行初始化,其他函數都不能對其賦值;(3)常成員函數的形式:類型 函數名(參數表) const,const是函數類型的組成部分,所以在聲明函數和定義函數時都要加關鍵字const;同樣我們以Employee(雇員)類為例:
1 #include "stdafx.h"
2 #include<string>
3 #include<iostream>
4
5 class Employee
6 {
7 private:
8 const std::string id;//常數據成員
9 const std::string name;//常數據成員
10 public:
11 Employee(std::string id,std::string name);
12 ~Employee();
13 void showEmployee();//普通成員函數
14 void showEmployee() const;//常成員函數
15 };
16
17 Employee::Employee(std::string id,std::string name):id(id),name(name)
18 {
19 //std::cout<<"構造對象employee"<<std::endl;
20 }
21
22 Employee::~Employee()
23 {
24 //std::cout<<"釋放對象employee內存空間"<<std::endl;
25 }
26
27 void Employee::showEmployee()
28 {
29 std::cout<<"普通成員函數:"<<std::endl;
30 std::cout<<"編號:"<<id<<std::endl;
31 std::cout<<"姓名:"<<name<<std::endl;
32 }
33
34 void Employee::showEmployee() const
35 {
36 std::cout<<"常成員函數:"<<std::endl;
37 std::cout<<"編號:"<<id<<std::endl;
38 std::cout<<"姓名:"<<name<<std::endl;
39 }
40
41 int main()
42 {
43 Employee employee("001","aa");
44 employee.showEmployee();
45
46 std::cout<<"********************************"<<std::endl;
47
48 Employee const const_employee("002","bb");//常對象
49 const_employee.showEmployee();
50
51 return 0;
52 }
結果:
從上述示例代碼中,我可以看到兩個同名函數void showEmployee(),一個是普通成員函數,一個是常成員函數,它們是重載的,由此說明const可以被用於對重載函數的區分;
3.C++的源程序基本上由3個部分組成:類的聲明部分、類的實現部分和類的使用部分,針對3個部分,C++中對應分為3個文件:類聲明文件(*.h文件)、類的實現文件(*.cpp)和類的使用文件(*.cpp,主函數main文件)。那麼為什麼C++中的要使用多文件,一個*.cpp類的使用文件就可解決的問題,為何那麼麻煩要分三步走呢?主要有以下幾個方面:(1)類的實現文件通常會比較大,將類的聲明和實現放在一起,不利於程序的閱讀、管理和維護。我們通常說接口應該和實現的部分分離,這樣可以更易於修改程序。(2)把類成員函數的實現放在聲明文件中和單獨放實現文件裡,在編譯時是不一樣的。前者是作為類的內聯函數來處理的。(3)對於軟件的廠商來說,它只需向用戶提供程序公開的接口,而不用公開程序源代碼。從這一點來看,我覺得C++在面向對象方面比C#更加明確,清晰。
4.最後還是一樣,我將用一個示例來總結一下今天所講的內容,同時將把程序按照C++多文件的原則分成3個文件來實現(開發工具:vs2010):
1.聲明文件*.h:
employee.h(雇員類的聲明文件)
View Code
salary.h(薪水類的聲明文件)
View Code
2.實現文件*.cpp:
employee.cpp(雇員類的實現文件)
View Code
salary.cpp(薪水類的實現文件)
View Code
3.使用文件*.cpp
main主函數文件
1 #include "stdafx.h"
2 #include<iostream>
3
4 #include "salary.h"
5 int main()
6 {
7 {
8 Salary salary(3000,3000,0,200,100,"001","aaa");
9 salary.showSalary();
10 }
11
12 return 0;
13 }
結果: