《C++ primer plus》學習筆記——第三章
面向物件程式設計的本質是設計並擴充套件自己的資料型別。
設計自己的資料型別就是讓型別與資料匹配。
一、簡單變數
1變數名
2.整型
3.整型short、int、long和long long
sizeof運算子可以用來檢查型別的長度,sizeof運算子返回型別或者變數的長度,單位為位元組。
位元組的含義依賴於實現,在一個系統中,兩位元組的int可能是16位,而在另一個系統中可能是32位。其次,標頭檔案climits中包含了關於整型限制的資訊,eg:INT_MAX為int的最大取值,CHAR_BIT為位元組的位數。
下面是64位的qindows 7系統跑出來的結果
// limits.cpp -- some integer limits #include <iostream> #include <climits> // use limits.h for older systems int main() { using namespace std; int n_int = INT_MAX; // initialize n_int to max int value short n_short = SHRT_MAX; // symbols defined in climits file long n_long = LONG_MAX; long long n_llong = LLONG_MAX; // sizeof operator yields size of type or of variable cout << "int is " << sizeof (int) << " bytes." << endl; cout << "short is " << sizeof n_short << " bytes." << endl; cout << "long is " << sizeof n_long << " bytes." << endl; cout << "long long is " << sizeof n_llong << " bytes." << endl; cout << endl; cout << "Maximum values:" << endl; cout << "int: " << n_int << endl; cout << "short: " << n_short << endl; cout << "long: " << n_long << endl; cout << "long long: " << n_llong << endl << endl; cout << "Minimum int value = " << INT_MIN << endl; cout << "Bits per byte = " << CHAR_BIT << endl; // cin.get(); return 0; }
1).運算子sizeof和標頭檔案limits
可以對型別名或者變數名使用sizeof運算子;
標頭檔案climits定義了符號常量,來表示型別的限制
符號常量——前處理器方式
climits檔案中包含與下面類似的語句行
#define INT_MAX 32767
在C++編譯過過程中,首先將原始碼傳遞給前處理器,在這裡,#define和#include一樣,是一個前處理器編譯指令,該指令告訴前處理器:在程式中查詢INT_MAX,並將所有的INT_MAX都替換成32767,因此,#define編譯指令的工作方式與文字編輯器或字處理器的全域性搜尋並替換命令相似。需要指出的是,有些標頭檔案,尤其是被設計成可用於C和C++中的標頭檔案,必須使用#define
C++有一種更好的建立符號常量的方法,使用關鍵字const
2).初始化
3).C++11初始化方式
除了=,還有大括號初始化器的使用
4無符號型別
要建立無符號版本的基本整型,只需要使用關鍵字unsigned來修改宣告即可
主要關注下面的一張圖片,C++符號整型超越限制的時候,出如何?
5選擇整型型別
具體的eg如下:
6整型字面值
C++使用前一(兩)位來標識數字常量的基數;
第一位是1-9,則基數是10(十進位制),eg:93是以10為基數;
第一位是0,第二位是1-7,基數是8(八進位制),eg:042=34(十進位制);
前兩位是0x或0X,則基數為16(十六進位制),eg:0x42為十六進位制數=66(十進位制);
eg:cout以十進位制格式顯示整數
// hexoct1.cpp -- shows hex and octal literals
#include <iostream>
#include<stdlib.h>
int main()
{
using namespace std;
int chest = 42; // decimal integer literal
int waist = 0x42; // hexadecimal integer literal
int inseam = 042; // octal integer literal
cout << "Monsieur cuts a striking figure!\n";
cout << "chest = " << chest << " (42 in decimal)\n";
cout << "waist = " << waist << " (0x42 in hex)\n";
cout << "inseam = " << inseam << " (042 in octal)\n";
// cin.get();
system("pause");
return 0;
}
eg:cout保持原進位制數輸出
主要是控制符dec、hex、oct的使用
// hexoct2.cpp -- display values in hex and octal
#include <iostream>
#include<stdlib.h>
using namespace std;
int main()
{
using namespace std;
int chest = 42;
int waist = 42;
int inseam = 42;
cout << "Monsieur cuts a striking figure!" << endl;
cout << "chest = " << chest << " (decimal for 42)" << endl;
cout << hex; // manipulator for changing number base
cout << "waist = " << waist << " (hexadecimal for 42)" << endl;
cout << oct; // manipulator for changing number base
cout << "inseam = " << inseam << " (octal for 42)" << endl;
// cin.get();
system("pause");
return 0;
}
7 C++確定常量的型別
例如,整型常量預設儲存為int;
首先看字尾,接下來考察長度。
3.1.8 char型別:字元和小整數
char型別是另外一種整型,它足夠長,能夠表示目標計算機系統中的所有基本符號——所有的字母、數字、標點符號等等。字符集中的字元是用數值編碼(ASCII碼)表示的,eg:字元A的編碼是65,字母M的額編碼是77
C++對字元用單引號,對字串使用雙引號
下面來看一個例子:
// morechar.cpp -- the char type and int type contrasted
#include <iostream>
int main()
{
using namespace std;
char ch = 'M'; // assign ASCII code for M to ch
int i = ch; // store same code in an int
cout << "The ASCII code for " << ch << " is " << i << endl;
cout << "Add one to the character code:" << endl;
ch = ch + 1; // change character code in ch
i = ch; // save new character code in i
cout << "The ASCII code for " << ch << " is " << i << endl;
// using the cout.put() member function to display a char
cout << "Displaying char ch using cout.put(ch): ";
cout.put(ch);
// using cout.put() to display a char constant
cout.put('!');
cout << endl << "Done" << endl;
// cin.get();
return 0;
}
在上述的程式當中,‘M’表示字元M的數值編碼(ASCII),因此將char變數ch初始化為‘M’,把ch設定為77。然後,程式將同樣的值賦值給int變數i,這樣ch和i都是77。最後,cout把ch顯示為M,把i顯示為77.
由於ch實際上是一個整數,因此可以對他使用整數操作。
cout.put()成員函式可以顯示字元,可以代替<<運算子。要通過物件(eg:cout)使用成員函式,必須用句點將物件名和函式名(put())連線起來使用,句點稱之為成員運算子。
一些常見的ASCII的對應情況,如下:
C++轉義序列
由於有些字元是不能直接通過鍵盤輸入到程式中,C++語言賦予了它們特殊的含義。
將他們作為字元常量的時候,應用單引號括起來,將他們放在字串中時,不要使用單引號
eg如下:
// hexoct2.cpp -- display values in hex and octal
#include <iostream>
#include<stdlib.h>
using namespace std;
int main()
{
using namespace std;
using namespace std;
cout << "\aOperation \"HyperHype\" is now activated!\n";
cout << "Enter your agent code:________\b\b\b\b\b\b\b\b";
long code;
cin >> code;
cout << "\aYou entered " << code << "...\n";
cout << "\aCode verified! Proceed with Plan Z3!\n";
// cin.get();
// cin.get();
cout<<sizeof('ji\n')<<endl;
cout<<sizeof("ji\n")<<endl;
system("pause");
return 0;
}
說明:程式使用退格字元將游標退到第一個下劃線處。
通用字元名
eg如下:
輸出:
說明:
2 const限定符
C++處理符號常量的方法就是,用const關鍵字來修改變數申明和初始化。
關鍵字const叫做限定符,限定了申明的含義,編譯器不孕尋再修改該常量的值。
eg:
命名規則:
C語言中的#define與C++中的const的區別
首先,const比#define好,原因如下:
1)const能夠明確指定型別
2)C++的作用域規則將定義限制在特定的函式或檔案中
3)const可以用於更加複雜的型別
3浮點數
能夠表示帶小數部分的數字
1 書寫浮點數
1)使用常用的標準小數點表示法
2)E表示法
eg:
2 浮點型別
C++提供了3種浮點型別:float,double,long double,這些型別是按它們可以表示的有效數位和允許的指數最小範圍來描述的,
通常,float為32位,double為64位,long double為80,96,或128位。
eg:
// hexoct2.cpp -- display values in hex and octal
#include <iostream>
#include<stdlib.h>
using namespace std;
int main()
{
using namespace std;
cout.setf(ios_base::fixed, ios_base::floatfield); // fixed-point
float tub = 10.0 / 3.0; // good to about 6 places
double mint = 10.0 / 3.0; // good to about 15 places
const float million = 1.0e6;
cout << "tub = " << tub;
cout << ", a million tubs = " << million * tub;
cout << ",\nand ten million tubs = ";
cout << 10 * million * tub << endl;
cout << "mint = " << mint << " and a million mints = ";
cout << million * mint << endl;
// cin.get();
system("pause");
return 0;
}
通常cout會刪除結尾的0,eg將3333333.250000->3333333.25,呼叫cout.setf()將覆蓋這種行為。
這裡,為啥float的精度比double低?
tub和mint都被初始化為:10.0/3.0=3.333333333333333333333…由於cout列印6位小數,因此,tub和mint都是精確的。而將每個數乘以一百萬以後,系統確保了float至少有6位是有效位,確保double至少有13位是有效位,故可知是精度限制
3 浮點常量
4浮點數的優缺點
相較於整數,浮點數的優點在於:
1)它們可以表示整數之間的值
2)由於有縮放因子,它們可以表示範圍大得多的數
缺點:浮點運算的速度比整數慢,且精度將降低
eg:
// hexoct2.cpp -- display values in hex and octal
#include <iostream>
#include<stdlib.h>
using namespace std;
int main()
{
using namespace std;
//cout.setf(ios_base::fixed, ios_base::floatfield); // fixed-point
float a = 2.34E+22f;
float b = a + 1.0f;
cout << "a = " << a << endl;
cout << "b - a = " << b - a << endl;
// cin.get();
system("pause");
return 0;
}
按照該程式字面的理解,結果應該為1。但是卻輸出了上述的結果,這是為啥呢?
4 C++算數運算子
下面是五種基本的C++算術運算子
// hexoct2.cpp -- display values in hex and octal
#include <iostream>
#include<stdlib.h>
using namespace std;
int main()
{
using namespace std;
float hats, heads;
cout.setf(ios_base::fixed, ios_base::floatfield); // fixed-point
cout << "Enter a number: ";
cin >> hats;
cout << "Enter another number: ";
cin >> heads;
cout << "hats = " << hats << "; heads = " << heads << endl;
cout << "hats + heads = " << hats + heads << endl;
cout << "hats - heads = " << hats - heads << endl;
cout << "hats * heads = " << hats * heads << endl;
cout << "hats / heads = " << hats / heads << endl;
system("pause");
return 0;
}
對於上述,畫箭頭的部分,說明如下:
1 運算子優先順序和結合性
1)*,/和%優先順序相同;
2)當兩個優先順序相同的運算子被同時作用於一個運算元的時候,結合性應該按照從左到右的方式,eg:
上面的答案應該是150
3)一個特別的例子如下:(知道即可)
2除法分支
1)如果兩個運算元都是整數,則結果會將小數部分丟棄,使得最後的結果是一個整數
2)如果其中有一個或兩個運算元都是浮點數,則小數部分保留,結果為浮點數。
eg:
// hexoct2.cpp -- display values in hex and octal
#include <iostream>
#include<stdlib.h>
using namespace std;
int main()
{
using namespace std;
cout.setf(ios_base::fixed, ios_base::floatfield);
cout << "Integer division: 9/5 = " << 9 / 5 << endl;
cout << "Floating-point division: 9.0/5.0 = ";
cout << 9.0 / 5.0 << endl;
cout << "Mixed division: 9.0/5 = " << 9.0 / 5 << endl;
cout << "double constants: 1e7/9.0 = ";
cout << 1.e7 / 9.0 << endl;
cout << "float constants: 1e7f/9.0f = ";
cout << 1.e7f / 9.0f << endl;
system("pause");
return 0;
}
3 求模運算子
適用於解決將一個量分成不同的整數單元的問題
eg:
4 型別轉換
1)初始化和賦值進行轉換
eg:
2)C++11以{}方式初始化時進行的轉換
在不同的整型之間轉換或將整型轉換為浮點型可能被允許,條件是編譯器知道目標變數能夠正確地儲存賦給它的值。
C++11將使用大括號的初始化稱為列表初始化,它對型別轉換的要求更嚴格。列表初始化不允許縮窄(narrowing),即變數的型別可能無法表示賦給它的值。
eg:
3)表示式中的轉換
當一個表示式中包含兩種不同的算術型別時,C++將執行兩種自動轉換:
首先,一些型別在出現時,便會自動轉換;
其次,有些型別在與其它型別同時出現在表示式中時將被轉換
4)傳遞引數時的轉換
傳遞引數時的型別轉換通常由C++函式原型控制
5)強制型別轉換
強制轉換的通用格式如下:
第一種格式是C語言
第二種格式是C++,新格式的想法是,要讓強制型別轉換就像是函式呼叫,這樣對內建型別的強制型別轉換就像是為使用者定義的類設計的型別轉換
static_cast<>可用於將值從一種數值型別轉換為另一種數值型別,這種運算子比傳統強制型別轉換更嚴格。
// hexoct2.cpp -- display values in hex and octal
#include <iostream>
#include<stdlib.h>
using namespace std;
int main()
{
using namespace std;
int auks, bats, coots;
// the following statement adds the values as double,
// then converts the result to int
auks = 19.99 + 11.99;
// these statements add values as int
bats = (int) 19.99 + (int) 11.99; // old C syntax
coots = int (19.99) + int (11.99); // new C++ syntax
cout << "auks = " << auks << ", bats = " << bats;
cout << ", coots = " << coots << endl;
char ch = 'Z';
cout << "The code for " << ch << " is "; // print as char
cout << int(ch) << endl; // print as int
cout << "Yes, the code is ";
cout << static_cast<int>(ch) << endl; // using static_cast
// cin.get();
system("pause");
return 0;
}
需要注意的是:兩種截斷的對比,
6)C++11中的auto申明
auto是C語言的一個關鍵字,使用較少,在初始化宣告中,如果使用關鍵字auto,而不指定變數的型別,編譯器將把變數的型別設定為與初始值相同。
zuto自動推斷型別並非為這種簡單情況而設計的,事實上,如果將其用於這種簡單情形,甚至可能會誤入歧途
最終的總結如下:
OOP指的是:面向物件程式設計