程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++編程思想部分精華提取

C++編程思想部分精華提取

編輯:C++入門知識

1、聲明與定義:
首先,必須知道“聲明”和“定義”之間的區別,因為這兩個術語在全書中會被確切地使用。“聲明”向計算機介紹名字,它說,“這個名字是什麼意思”。而“定義”為這個名字分配
存儲空間。無論涉及到變量時還是函數時含義都一樣。無論在哪種情況下,編譯器都在“定義”處分配存儲空間。對於變量,編譯器確定這個變量占多少存儲單元,並在內存中產生存放它們的空間。對於函數,編譯器產生代碼,並為之分配存儲空間。函數的存儲空間中有一個由使用不帶參數表或帶地址操作符的函數名產生的指針。定義也可以是聲明。如果該編譯器還沒有看到過名字A,程序員定義int A,則編譯器馬上為這個名字分配存儲地址。聲明常常使用於e x t e r n關鍵字。如果我們只是聲明變量而不是定義它,則要求使用e x t e r n。對於函數聲明, e x t e r n是可選的,不帶函數體的函數名連同參數表或返回值,自動地作為一個聲明。函數原型包括關於參數類型和返回值的全部信息。int f(float,char);是一個函數原型,因為它不僅介紹f這個函數的名字,而且告訴編譯器這個函數有什麼樣的參數和返回值,使得編譯器能對參數和返回值做適當的處理。C + +要求必須寫出函數原型,因為它增加了一個重要的安全層。
extern int i;//聲明
extern float f(float);//聲明
float b;//聲明+定義
float f(float a){//定義
return a+1.0;
}
int i;//定義
int h(int x){//聲明+定義
return x+1;
}
main(){
b=1.0;
i=2;
f(b);
h(i);
}
在函數聲明時,參數名可給出也可不給出。而在定義時,它們是必需的。這在C語言中確實如此,但在C + +中並不一定。
2、句柄類:
C + +中的存取控制允許將實現與接口部分分開,但實現的隱藏是不完全的。編譯器必須知道一個對象的所有部分的聲明,以便創建和管理它。我們可以想象一種只需聲明一個對象的公共接口部分的編程語言,而將私有的實現部分隱藏起來。但C + +在編譯期間要盡可能多地做靜態類型檢查。這意味著盡早捕獲錯誤,也意味著程序具有更高的效率。然而這對私有的實現部分來說帶來兩個影響:一是即使程序員不能輕易地訪問實現部分,但他可以看到它;二是造成一些不必要的重復編譯。
可見的實現部分:
有些項目不可讓最終用戶看到其實現部分。例如可能在一個庫的頭文件中顯示一些策略信息,但公司不想讓這些信息被競爭對手獲得。比如從事一個安全性很重要的系統(如加密算法),我們不想在文件中暴露任何線索,以防有人破譯我們的代碼。或許我們把庫放在了一個“有敵意”的環境中,在那裡程序員會不顧一切地用指針和類型轉換存取我們的私有成員。在所有這些情況下,就有必要把一個編譯好的實際結構放在實現文件中,而不是讓其暴露在頭文件中。
減少重復編譯:
在我們的編程環境中,當一個文件被修改,或它所依賴的文件包含的頭文件被修改時,項目負責人需要重復編譯這些文件。這意味著無論何時程序員修改了一個類,無論是修改公共的接口部分,還是私有的實現部分,他都得再次編譯包含頭文件的所有文件。對於一個大的項目而言,在開發初期這可能非常難以處理,因為實現部分可能需要經常改動;如果這個項目非常大,用於編譯的時間過多就可能妨礙項目的完成。解決這個問題的技術有時叫句柄類( handle classes)或叫“Cheshire Cat”[ 1 ]。有關實現的任何東西都消失了,只剩一個單一的指針“ s m i l e”。該指針指向一個結構,該結構的定義與其所有的成員函數的定義一樣出現在實現文件中。這樣,只要接口部分不改變,頭文件就不需變
動。而實現部分可以按需要任意更動,完成後只要對實現文件進行重新編譯,然後再連接到項目中。這裡有個說明這一技術的簡單例子。頭文件中只包含公共的接口和一個簡單的沒有完全指定的類指針。這是所有客戶程序員都能看到的。這行
struct cheshire;
是一個沒有完全指定的類型說明或類聲明(一個類的定義包含類的主體)。它告訴編譯器,cheshire 是一個結構的名字,但沒有提供有關該結構的任何東西。這對產生一個指向結構的指針來說已經足夠了。但我們在提供一個結構的主體部分之前不能創建一個對象。在這種技術裡,包含具體實現的結構主體被隱藏在實現文件中。
#ifndef HANDLE_H
#define HANDLE_H
class handle{
struct cheshire;
cheshire *smile;
public:
void initialize();
void cleanup();
int read();
void change(int);
};
#endif
這是所有客戶程序員都能看到的。這行
struct cheshire;
是一個沒有完全指定的類型說明或類聲明(一個類的定義包含類的主體)。它告訴編譯器,cheshire 是一個結構的名字,但沒有提供有關該結構的任何東西。這對產生一個指向結構的指針來說已經足夠了。但我們在提供一個結構的主體部分之前不能創建一個對象。在這種技術裡,包含具體實現的結構主體被隱藏在實現文件中。
#include "handle.h"
struct handle::cheshire{
int i;
};
void handle::initialize(){
smile=(cheshire *)malloc(sizeof(cheshire));
assert(smile);
smile->i=0;
}
void handle::cheanup(){
free(smile);
}
int handle::read(){
return smile->i;
}
void handle::change(int x){
smile->i=x;
}
cheshire 是一個嵌套結構,所以它必須用范圍分解符定義
struct handle::cheshire {
在h a n d l e : : i n i t i a l i z e ( )中,為cheshire struct分配存儲空間[ 1 ],在h a n d l e : : c l e a n u p ( )中這些空間被釋放。這些內存被用來代替類的所有私有部分。當編譯H A N D L E . C P P時,這個結構的定義被隱藏在目標文件中,沒有人能看到它。如果改變了c h e s h i r e的組成,唯一要重新編譯的是H A N D L E . C P P,因為頭文件並沒有改動。句柄(h a n d l e)的使用就像任何類的使用一樣,包含頭文件、創建對象、發送信息。
#include "handle.h"
main(){
handle u;
u.initialize();
u.read();
u.change(2);
}
客戶程序員唯一能存取的就是公共的接口部分,因此,只是修改了在實現中的部分,這些文件就不須重新編譯。雖然這並不是完美的信息隱藏,但畢竟是一大進步
作者:fengzhishang2019

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved