C++ 編程指南
- ■ C++環境安裝
- ■ C++ 基本語法
- ■ 預定義宏
- ■ # 和 ## 運算符
- ■ C++ 引用
- ■ C++ 命名空間
- ■ 定義命名空間
- ■ using 指令
- ■ 嵌套的命名空間
- ■ String類
- ■ 類
- ■ 類的static靜態成員
- ■ C++ 繼承
- ■ 繼承類型 public、protected 或 private
- ■ 訪問控制和繼承
- ■ 多繼承
- ■ 數據抽象
- ■ C++ 指針
- ■ this 指針
- ■ 指向類的指針
- ■ 內聯函數
- ■ 構造& 析構函數
- ■ 構造函數
- ■ 析構函數
- ■ 拷貝構造函數
- ■ 友元
- ■ 友元類
- ■ 友元函數
- ■ C++ 函數重載
- ■ C++ 多態
- ■ 靜態多態,或靜態鏈接
- ■ 動態鏈接,或后期綁定
- ■ 虛函數
- ■ 純虛函數
- ■ C++ 標準流,文件流
- ■ C++ 異常處理
- ■ C++ 動態內存
- ■ C++ 模板
- ■ 函數模板
- ■ 類模板
- ■ C++ 信號處理
- ■
- ■
- ■ C++ 多線程
- ■
- ■
- ■ C++ 標準庫
- ■
- ■
■ C++環境安裝
C++環境安裝
■ C++ 基本語法
■ 預定義宏
宏 | 描述 |
---|---|
LINE | 這會在程序編譯時包含當前行號。 |
FILE | 這會在程序編譯時包含當前文件名。 |
DATE | 這會包含一個形式為 month/day/year 的字符串,它表示把源文件轉換為目標代碼的日期。 |
TIME | 這會包含一個形式為 hour:minute:second 的字符串,它表示程序被編譯的時間。 |
#include <iostream>
using namespace std;
int main ()
{cout << "Value of __LINE__ : " << __LINE__ << endl;cout << "Value of __FILE__ : " << __FILE__ << endl;cout << "Value of __DATE__ : " << __DATE__ << endl;cout << "Value of __TIME__ : " << __TIME__ << endl; return 0;
}當上面的代碼被編譯和執行時,它會產生下列結果:
Value of __LINE__ : 6
Value of __FILE__ : test.cpp
Value of __DATE__ : Feb 28 2011
Value of __TIME__ : 18:52:48
■ # 和 ## 運算符
■ C++ 引用
int i = 17;
int& r = i; //為 i 聲明引用變量
double& s = d; r = 14; //引用使用
■ C++ 命名空間
■ 定義命名空間
namespace namespace_name {// 代碼聲明
}
使用命名空間變量或函數
name::code; // code 可以是變量或函數
示例一:
#include <iostream>
using namespace std;// 第一個命名空間
namespace first_space{void func(){cout << "Inside first_space" << endl;}
}
// 第二個命名空間
namespace second_space{void func(){cout << "Inside second_space" << endl;}
}
int main ()
{ // 調用第一個命名空間中的函數first_space::func();// 調用第二個命名空間中的函數second_space::func(); return 0;
}
它會產生下列結果:
Inside first_space
Inside second_space
■ using 指令
使用 using namespace 指令,這樣在使用命名空間時就可以不用在前面加上命名空間的名稱。
這個指令會告訴編譯器,后續的代碼將使用指定的命名空間中的名稱。
#include <iostream>
using namespace std;// 第一個命名空間
namespace first_space{void func(){cout << "Inside first_space" << endl;}
}
// 第二個命名空間
namespace second_space{void func(){cout << "Inside second_space" << endl;}
}
using namespace first_space; //這個指令會告訴編譯器,后續的代碼將使用指定的命名空間中的名稱。
int main ()
{ // 調用第一個命名空間中的函數func();return 0;
}
using 指令也可以用來指定命名空間中的特定項目
using std::cout; //使用 std 命名空間中的 cout 部分
示例一:使用 std 命名空間中的 cout 部分
#include <iostream>
using std::cout;int main ()
{cout << "std::endl is used with std!" << std::endl;return 0;
}
■ 嵌套的命名空間
命名空間可以嵌套
namespace namespace_name1 {// 代碼聲明namespace namespace_name2 {// 代碼聲明}
}
通過使用 :: 運算符來訪問嵌套的命名空間中的成員:
// 訪問 namespace_name2 中的成員
using namespace namespace_name1::namespace_name2;// 訪問 namespace_name1 中的成員
using namespace namespace_name1;
示例一:嵌套的命名空間使用
#include <iostream>
using namespace std;// 第一個命名空間
namespace first_space{void func(){cout << "Inside first_space" << endl;}// 第二個命名空間namespace second_space{void func(){cout << "Inside second_space" << endl;}}
}
using namespace first_space::second_space;
int main ()
{ // 調用第二個命名空間中的函數func(); return 0;
}
示例二:全局變量 a 表達為 ::a,用于當有同名的局部變量時來區別兩者。
#include <iostream>
using namespace std;
namespace A
{int a = 100;namespace B //嵌套一個命名空間B{int a =20;}
}int a = 200;//定義一個全局變量int main(int argc, char *argv[])
{cout <<"A::a ="<< A::a << endl;cout <<"A::B::a ="<<A::B::a << endl;cout <<"a ="<<a << endl;cout <<"::a ="<<::a << endl;int a = 30;cout <<"a ="<<a << endl;cout <<"::a ="<<::a << endl;return 0;
}
結果:
A::a =100
A::B::a =20
a =200 //全局變量a
::a =200
a =30 //局部變量a
::a =200
■ String類
C++ 標準庫提供了 string 類類型。
示例一:
#include <iostream>
#include <string>using namespace std;int main ()
{string str1 = "runoob";string str2 = "google";string str3;int len ;// 復制 str1 到 str3str3 = str1;cout << "str3 : " << str3 << endl;// 連接 str1 和 str2str3 = str1 + str2;cout << "str1 + str2 : " << str3 << endl;// 連接后,str3 的總長度len = str3.size();cout << "str3.size() : " << len << endl;return 0;
}結果:
str3 : runoob
str1 + str2 : runoobgoogle
str3.size() : 12
–
■ 類
■ 類的static靜態成員
- 類的變量和函數都可以被聲明為靜態的。
- static 關鍵字來把類成員定義為靜態的。
- 當我們聲明類的成員為靜態時,這意味著無論創建多少個類的對象,靜態成員都只有一個副本。
- 靜態成員在類的所有對象中是共享的。
- 在創建第一個對象時,所有的靜態數據都會被初始化為零
- 不能把靜態成員的初始化放置在類的定義中。
- 在類的外部通過使用范圍解析運算符 :: 來重新聲明靜態變量從而對它進行初始化
示例一:
#include <iostream>using namespace std;class Box
{public:static int objectCount;// 構造函數定義Box(double l=2.0, double b=2.0, double h=2.0){cout <<"Constructor called." << endl;length = l;breadth = b;height = h;// 每次創建對象時增加 1objectCount++;}double Volume(){return length * breadth * height;}static int getCount(){return objectCount;}private:double length; // 長度double breadth; // 寬度double height; // 高度
};// 初始化類 Box 的靜態成員
int Box::objectCount = 0;int main(void)
{// 在創建對象之前輸出對象的總數cout << "Inital Stage Count: " << Box::getCount() << endl;Box Box1(3.3, 1.2, 1.5); // 聲明 box1Box Box2(8.5, 6.0, 2.0); // 聲明 box2// 在創建對象之后輸出對象的總數cout << "Final Stage Count: " << Box::getCount() << endl;return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:
Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2
■ C++ 繼承
已有的類稱為基類,新建的類稱為派生類。
示例一:基類 & 派生類
// 基類
class Animal {// eat() 函數// sleep() 函數
};//派生類
class Dog : public Animal {// bark() 函數
};
■ 繼承類型 public、protected 或 private
繼承類型 | 說明 |
---|---|
公有繼承(public): | 當一個類派生自公有基類時,基類的公有成員也是派生類的公有成員,基類的保護成員也是派生類的保護成員,基類的私有成員不能直接被派生類訪問,但是可以通過調用基類的公有和保護成員來訪問。 |
保護繼承(protected): | 當一個類派生自保護基類時,基類的公有和保護成員將成為派生類的保護成員。 |
私有繼承(private): | 當一個類派生自私有基類時,基類的公有和保護成員將成為派生類的私有成員。 |
■ 訪問控制和繼承
派生類可以訪問基類中所有成員訪問權限如下:
訪問 | public | protected | private |
---|---|---|---|
同一個類 | yes | yes | yes |
派生類 | yes | yes | no |
外部的類 | yes | no | no |
一個派生類繼承了所有的基類方法,但下列情況除外:
基類的構造函數、析構函數和拷貝構造函數。
基類的重載運算符。
基類的友元函數。
■ 多繼承
多繼承即一個子類可以有多個父類,它繼承了多個父類的特性。
class <派生類名>:<繼承方式1><基類名1>,<繼承方式2><基類名2>,…
{<派生類類體>
};// 派生類
class Rectangle: public Shape, public PaintCost
{public:int getArea(){ return (width * height); }
};
■ 數據抽象
類的內部受到保護,不會因無意的用戶級錯誤導致對象狀態受損。
數據抽象是一個把實現細節與相關的數據分離開的概念。
#include <iostream>
using namespace std;
class Adder{public:// 構造函數Adder(int i = 0){total = i;}// 對外的接口void addNum(int number){total += number;}// 對外的接口int getTotal(){return total;};private:// 對外隱藏的數據int total;
};
int main( )
{Adder a; a.addNum(10);a.addNum(20);a.addNum(30); cout << "Total " << a.getTotal() <<endl;return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:
Total 60
■ C++ 指針
■ this 指針
this 指針是一個特殊的指針,它指向當前對象的實例。
每一個對象都能通過 this 指針來訪問自己的地址。
友元函數沒有 this 指針,因為友元不是類的成員,只有成員函數才有 this 指針。
■ 指向類的指針
示例一:聲明和初始化指向類的指針
#include <iostream>class MyClass {
public:int data;void display() {std::cout << "Data: " << data << std::endl;}
};
int main() {// 創建類對象MyClass obj;obj.data = 42;// 聲明和初始化指向類的指針MyClass *ptr = &obj;// 通過指針訪問成員變量std::cout << "Data via pointer: " << ptr->data << std::endl;// 通過指針調用成員函數ptr->display();return 0;
}
示例二:動態分配內存
#include <iostream>
class MyClass {
public:int data;void display() {std::cout << "Data: " << data << std::endl;}
};int main() {// 動態分配內存創建類對象MyClass *ptr = new MyClass;ptr->data = 42;// 通過指針調用成員函數ptr->display();// 釋放動態分配的內存delete ptr;return 0;
}
示例三:指向類的指針作為函數參數
#include <iostream>
class MyClass {
public:int data;void display() {std::cout << "Data: " << data << std::endl;}
};
// 函數接受指向類的指針作為參數
void processObject(MyClass *ptr) {ptr->display();
}
int main() {MyClass obj;obj.data = 42;// 將指向類的指針傳遞給函數processObject(&obj);return 0;
}
■ 內聯函數
C++ 內聯函數是通常與類一起使用。如果一個函數是內聯的,那么在編譯時,編譯器會把該函數的代碼副本放置在每個調用該函數的地方。
對內聯函數進行任何修改,都需要重新編譯函數的所有客戶端,因為編譯器需要重新更換一次所有的代碼,否則將會繼續使用舊的函數。
如果想把一個函數定義為內聯函數,則需要在函數名前面放置關鍵字 inline
內聯函數作用:
引入內聯函數的目的是為了解決程序中函數調用的效率問題。
程序在編譯器編譯的時候,編譯器將程序中出現的內聯函數的調用表達式用內聯函數的函數體進行替換,而對于其他的函數,都是在運行時候才被替代。這其實就是個空間代價換時間的節省。
內聯函數確定:
- 內聯那些包含循環或 switch 語句的函數常常是得不償失 (除非在大多數情況下, 這些循環或 switch 語句從不被執行).
- 有些函數即使聲明為內聯的也不一定會被編譯器內聯, 比如虛函數和遞歸函數就不會被正常內聯. 通常, 遞歸函數不應該聲明成內聯函數
示例一:聲明內聯函數 inline
#include <iostream>
using namespace std;inline int Max(int x, int y)
{return (x > y)? x : y;
}// 程序的主函數
int main( )
{cout << "Max (20,10): " << Max(20,10) << endl;cout << "Max (0,200): " << Max(0,200) << endl;cout << "Max (100,1010): " << Max(100,1010) << endl;return 0;
}當上面的代碼被編譯和執行時,它會產生下列結果:
Max (20,10): 20
Max (0,200): 200
Max (100,1010): 1010
■ 構造& 析構函數
■ 構造函數
示例一:無參構造
class Line
{public:void setLength( double len );double getLength( void );Line(double len); // 這是構造函數private:double length;
};// 成員函數定義,包括構造函數
Line::Line( double len)
{cout << "Object is being created, length = " << len << endl;length = len;
}
//使用聲明
Line line(10.0);
示例二:使用初始化列表來初始化字段
class Line
{public:void setLength( double len );double getLength( void );Line(double len); // 這是構造函數private:double length;
};
Line::Line( double len): length(len)
{cout << "Object is being created, length = " << len << endl;
}上面的語法等同于如下語法:
Line::Line( double len)
{length = len;cout << "Object is being created, length = " << len << endl;
}
■ 析構函數
class Line
{public:void setLength( double len );double getLength( void );Line(); // 這是構造函數聲明~Line(); // 這是析構函數聲明private:double length;
};
Line::~Line(void)
{cout << "Object is being deleted" << endl;
}// 程序的主函數
int main( )
{Line line;// 設置長度line.setLength(6.0); cout << "Length of line : " << line.getLength() <<endl;return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:
Object is being created
Length of line : 6
Object is being deleted
■ 拷貝構造函數
拷貝構造函數是一種特殊的構造函數,它在創建對象時,是使用同一類中之前創建的對象來初始化新創建的對象。
拷貝構造函數通常用于:
- 通過使用另一個同類型的對象來初始化新創建的對象。
- 復制對象把它作為參數傳遞給函數。
- 復制對象,并從函數返回這個對象。
如果在類中沒有定義拷貝構造函數,編譯器會自行定義一個。如果類帶有指針變量,并有動態內存分配,則它必須有一個拷貝構造函數。
拷貝構造函數的最常見形式如下:
classname (const classname &obj) {// 構造函數的主體
}
示例一 拷貝構造函數
class Line
{public:int getLength( void );Line( int len ); // 簡單的構造函數Line( const Line &obj); // 拷貝構造函數~Line(); // 析構函數private:int *ptr;
};
// 成員函數定義,包括構造函數
Line::Line(int len)
{cout << "調用構造函數" << endl;// 為指針分配內存ptr = new int;*ptr = len;
}Line::Line(const Line &obj)
{cout << "調用拷貝構造函數并為指針 ptr 分配內存" << endl;ptr = new int;*ptr = *obj.ptr; // 拷貝值
}
Line::~Line(void)
{cout << "釋放內存" << endl;delete ptr; //要記得釋放內存
}
int Line::getLength( void )
{return *ptr;
}void display(Line obj)
{cout << "line 大小 : " << obj.getLength() <<endl;
}// 程序的主函數
int main( )
{Line line(10);display(line);return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:
調用構造函數
調用拷貝構造函數并為指針 ptr 分配內存
line 大小 : 10
釋放內存
釋放內存
#include <iostream>using namespace std;class Line
{public:int getLength( void );Line( int len ); // 簡單的構造函數Line( const Line &obj); // 拷貝構造函數~Line(); // 析構函數private:int *ptr;
};// 成員函數定義,包括構造函數
Line::Line(int len)
{cout << "調用構造函數" << endl;// 為指針分配內存ptr = new int;*ptr = len;
}Line::Line(const Line &obj)
{cout << "調用拷貝構造函數并為指針 ptr 分配內存" << endl;ptr = new int;*ptr = *obj.ptr; // 拷貝值
}Line::~Line(void)
{cout << "釋放內存" << endl;delete ptr;
}
int Line::getLength( void )
{return *ptr;
}void display(Line obj)
{cout << "line 大小 : " << obj.getLength() <<endl;
}// 程序的主函數
int main( )
{Line line1(10); //調用構造函數Line line2 = line1; // 這里也調用了拷貝構造函數display(line1); // 這里也調用了拷貝構造函數display(line2); // 這里也調用了拷貝構造函數return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:調用構造函數
調用拷貝構造函數并為指針 ptr 分配內存
調用拷貝構造函數并為指針 ptr 分配內存
line 大小 : 10
釋放內存
調用拷貝構造函數并為指針 ptr 分配內存
line 大小 : 10
釋放內存
釋放內存
釋放內存
■ 友元
■ 友元類
整個類及其所有成員都是友元。
■ 友元函數
類的友元函數是定義在類內部,但有權訪問類的所有私有(private)成員和保護(protected)成員。
盡管友元函數的原型有在類的定義中出現過,但是友元函數并不是成員函數。
友元函數沒有 this 指針,因為友元不是類的成員,只有成員函數才有 this 指針。
示例一:在類定義中函數原型前使用關鍵字 friend,表示這個函數是類的友元函數,在函數中可以訪問類中的成員函數或成員變量
#include <iostream>
using namespace std;
class Box
{double width;
public:friend void printWidth( Box box ); //聲明友元函數,但是友元函數并不是成員函數。void setWidth( double wid );
};// 成員函數定義
void Box::setWidth( double wid )
{width = wid;
}// 請注意:printWidth() 不是任何類的成員函數
void printWidth( Box box )
{/* 因為 printWidth() 是 Box 的友元,它可以直接訪問該類的任何成員 */cout << "Width of box : " << box.width <<endl;
}// 程序的主函數
int main( )
{Box box;// 使用成員函數設置寬度box.setWidth(10.0);// 使用友元函數輸出寬度printWidth( box );return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:
Width of box : 10
■ C++ 函數重載
C++ 函數重載
■ C++ 多態
多態按字面的意思就是多種形態.
當類之間存在層次結構,并且類之間是通過繼承關聯時,就會用到多態。
C++ 多態意味著調用成員函數時,會根據調用函數的對象的類型來執行不同的函數。
■ 靜態多態,或靜態鏈接
示例一:靜態多態,或靜態鏈接, 有時候這也被稱為早綁定
調用函數 area() 被編譯器設置為基類中的版本,這就是所謂的靜態多態,或靜態鏈接 - 函數調用在程序執行前就準備好了。有時候這也被稱為早綁定,
#include <iostream>
using namespace std;class Shape {protected:int width, height;public:Shape( int a=0, int b=0){width = a;height = b;}int area(){cout << "Parent class area :" <<endl;return 0;}
};
class Rectangle: public Shape{public:Rectangle( int a=0, int b=0):Shape(a, b) { }int area (){ cout << "Rectangle class area :" <<endl;return (width * height); }
};
class Triangle: public Shape{public:Triangle( int a=0, int b=0):Shape(a, b) { }int area (){ cout << "Triangle class area :" <<endl;return (width * height / 2); }
};
// 程序的主函數
int main( )
{Shape *shape;Rectangle rec(10,7);Triangle tri(10,5);// 存儲矩形的地址shape = &rec;// 調用矩形的求面積函數 areashape->area();// 存儲三角形的地址shape = &tri;// 調用三角形的求面積函數 areashape->area();return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:
Parent class area :
Parent class area :
■ 動態鏈接,或后期綁定
在基類中使用關鍵字 virtual 聲明的函數。在派生類中重新定義基類中定義的虛函數時,會告訴編譯器不要靜態鏈接到該函數。這種操作被稱為動態鏈接,或后期綁定。
示例一:聲明前放置關鍵字 virtual
*此時,編譯器看的是指針的內容,而不是它的類型。因此,由于 tri 和 rec 類的對象的地址存儲在 shape 中 所以會調用各自的 area() 函數。
class Shape {protected:int width, height;public:Shape( int a=0, int b=0){width = a;height = b;}virtual int area() //添加virtual變成虛函數{cout << "Parent class area :" <<endl;return 0;}
};
修改后,當編譯和執行前面的實例代碼時,它會產生以下結果:
Rectangle class area :
Triangle class area :
■ 虛函數
虛函數 是在基類中使用關鍵字 virtual 聲明的函數。在派生類中重新定義基類中定義的虛函數時,會告訴編譯器不要靜態鏈接到該函數。
■ 純虛函數
基類中定義虛函數,以便在派生類中重新定義該函數更好地適用于對象,但是您在基類中又不能對虛函數給出有意義的實現,這個時候就會用到純虛函數。
**
示例一:virtual int area() = 0; 告訴編譯器,函數沒有主體,上面的虛函數是純虛函數。
class Shape {protected:int width, height;public:Shape( int a=0, int b=0){width = a;height = b;}// pure virtual functionvirtual int area() = 0; //= 0 告訴編譯器,函數沒有主體,上面的虛函數是純虛函數。
};
■ C++ 標準流,文件流
C++ 標準流,文件流
■ C++ 異常處理
C++ 異常處理
■ C++ 動態內存
malloc() 函數在 C 語言中就出現了,在 C++ 中仍然存在
new 與 malloc() 函數相比,其主要的優點是,new 不只是分配了內存,它還創建了對象。
動態分配,一維數組
// 動態分配,數組長度為 m
int *array=new int [m];//釋放內存
delete [] array;
動態分配,二維數組
int **array;
// 假定數組第一維長度為 m, 第二維長度為 n
// 動態分配空間
array = new int *[m];
for( int i=0; i<m; i++ )
{array[i] = new int [n];
}
//釋放
for( int i=0; i<m; i++ )
{delete [] array[i];
}
delete [] array;
動態分配,三維數組
int ***array;
// 假定數組第一維為 m, 第二維為 n, 第三維為h
// 動態分配空間
array = new int **[m];
for( int i=0; i<m; i++ )
{array[i] = new int *[n];for( int j=0; j<n; j++ ){array[i][j] = new int [h];}
}
//釋放
for( int i=0; i<m; i++ )
{for( int j=0; j<n; j++ ){delete[] array[i][j];}delete[] array[i];
}
delete[] array;
對象的動態內存分配
#include <iostream>
using namespace std;class Box
{public:Box() { cout << "調用構造函數!" <<endl; }~Box() { cout << "調用析構函數!" <<endl; }
};int main( )
{Box* myBoxArray = new Box[4];delete [] myBoxArray; // 刪除數組return 0;
}
■ C++ 模板
■ 函數模板
示例一:
#include <iostream>
#include <string>
using namespace std;template <typename T>
inline T const& Max (T const& a, T const& b)
{ return a < b ? b:a;
}
int main ()
{ int i = 39;int j = 20;cout << "Max(i, j): " << Max(i, j) << endl; double f1 = 13.5; double f2 = 20.7; cout << "Max(f1, f2): " << Max(f1, f2) << endl; string s1 = "Hello"; string s2 = "World"; cout << "Max(s1, s2): " << Max(s1, s2) << endl; return 0;
}
當上面的代碼被編譯和執行時,它會產生下列結果:
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World
■ 類模板
示例一:類模板
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>using namespace std;template <class T>
class Stack { private: vector<T> elems; // 元素 public: void push(T const&); // 入棧void pop(); // 出棧T top() const; // 返回棧頂元素bool empty() const{ // 如果為空則返回真。return elems.empty(); }
}; template <class T>
void Stack<T>::push (T const& elem)
{ // 追加傳入元素的副本elems.push_back(elem);
} template <class T>
void Stack<T>::pop ()
{ if (elems.empty()) { throw out_of_range("Stack<>::pop(): empty stack"); }// 刪除最后一個元素elems.pop_back();
} template <class T>
T Stack<T>::top () const
{ if (elems.empty()) { throw out_of_range("Stack<>::top(): empty stack"); }// 返回最后一個元素的副本 return elems.back();
} int main()
{ try { Stack<int> intStack; // int 類型的棧 Stack<string> stringStack; // string 類型的棧 // 操作 int 類型的棧 intStack.push(7); cout << intStack.top() <<endl; // 操作 string 類型的棧 stringStack.push("hello"); cout << stringStack.top() << std::endl; stringStack.pop(); stringStack.pop(); } catch (exception const& ex) { cerr << "Exception: " << ex.what() <<endl; return -1;}
}
它會產生下列結果:
7
hello
Exception: Stack<>::pop(): empty stack