【C++ 编程指南】

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静态成员

  1. 类的变量和函数都可以被声明为静态的
  2. static 关键字来把类成员定义为静态的。
  3. 当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。
  4. 静态成员在类的所有对象中是共享的。
  5. 在创建第一个对象时,所有的静态数据都会被初始化为零
  6. 不能把静态成员的初始化放置在类的定义中。
  7. 在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化

示例一:

#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):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

■ 访问控制和继承

派生类可以访问基类中所有成员访问权限如下:

访问publicprotectedprivate
同一个类yesyesyes
派生类yesyesno
外部的类yesnono

一个派生类继承了所有的基类方法,但下列情况除外:
基类的构造函数、析构函数和拷贝构造函数。
基类的重载运算符。
基类的友元函数。

■ 多继承

多继承即一个子类可以有多个父类,它继承了多个父类的特性。

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

■ 虚继承

class A {
public:	A() {cout << "A(): " << endl;}
};
class B : virtual public A {  //
public:B() :A() {cout << "B():A(): " << endl;}
};
class C : virtual public A {
public:C() :A() {cout << "C():A(): " << endl;}
};
class D : public C, public B {
public:D() {cout << "D() " << endl;}
};
void test() {D d;
}

在这里插入图片描述
这个输出代表了对象的构造顺序。根据输出可以看出:

  • 首先,类 A 的构造函数被调用,输出 "A(): "。
  • 接着,类 C 的构造函数被调用,由于 C 类继承了虚基类 A,所以会先调用 A 的构造函数,输出 "C():A(): "。
  • 然后,类 B 的构造函数被调用,同样会先调用 A 的构造函数,输出 "B():A(): "。
  • 最后,类 D 的构造函数被调用,由于 D 类同时继承了类 C 和类 B,而这两个类都已经初始化过虚基类 A 的部分,所以在 D 的构造函数中不需要再次调用 A 的构造函数。

由于类D是多重继承体系中的最底层类,它同时继承了类C和类B,而这两个类都间接继承了虚基类A。在这种情况下,编译器会负责确保虚基类A只被初始化一次

■ 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

内联函数作用:
引入内联函数的目的是为了解决程序中函数调用的效率问题
程序在编译器编译的时候,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换,而对于其他的函数,都是在运行时候才被替代。这其实就是个空间代价换时间的节省。

内联函数确定:

  1. 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行).
  2. 有些函数即使声明为内联的也不一定会被编译器内联, 比如虚函数和递归函数就不会被正常内联. 通常, 递归函数不应该声明成内联函数

示例一:声明内联函数 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

■ C++ 信号处理

■ C++ 多线程

■ C++ 标准库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/268492.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最新版阿里云Linux CentOS7 ecs-user用户安装Mysql8详细教程(超简单)

经过两天的踩坑后&#xff0c;终于成功安装&#xff0c;并找到了最快捷的安装方式。接下来就由我来给大家介绍不踩坑安装大法&#xff01; 一、下载Mysql 首先前往Mysql官网下载 MySQL官方下载地址 第一步&#xff0c;选择安装包&#xff0c;这是最关键的一步&#xff0c;选错安…

css样式元素的相对定位,绝对定位,固定定位等元素定位运用技巧详解

文章目录 1.相对定位 relative2.绝对定位 absolute3.固定定位4.display 转换元素5.float浮动6.float产生内容塌陷问题7.overflow CSS样式学习宝典&#xff0c;关注点赞加收藏&#xff0c;防止迷路哦 在CSS中关于定位的内容是&#xff1a;position:relative | absolute | static…

uniapp聊天记录本地存储(详细易懂)

目录 目录 1、通过websocket拿取数据 2、获取聊天数据 3、聊天信息存储 、更新 4、读取聊天记录 5、发送信息&#xff0c;信息获取 6、最终效果 1.聊天信息的存储格式 2、样式效果 写聊天项目&#xff0c;使用到了本地存储。需要把聊天信息保存在本地&#xff0c;实时获…

第105讲:Mycat垂直分表实战:从规划到解决问题的完整指南

文章目录 1.垂直分表的背景2.垂直分表案例实战2.1.垂直分表规划2.2.配置Mycat实现垂直分表2.3.重启Mycat2.4.在Mycat命令行中导入数据结构2.5.查看由Mycat分表后每个分片上存储的表2.6.Mycat垂直分表后可能遇到的问题2.7.垂直分表完成 1.垂直分表的背景 我们的商城系统数据库&…

软件测试项目实战,某购物车/测试点分析实战(详细步骤)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 第一步&#xff1…

winform 输出运行设备的mac地址

winform定制一个代码段 输出运行设备的mac码此方法获取的是运行设备上的物理网卡的MAC地址&#xff0c;并不包括虚拟网卡或无线网卡的MAC地址。当设备具有多个网卡时&#xff0c;它只返回第一个正常运行的网卡的MAC地址。如果未找到任何网卡&#xff0c;则返回"未找到MAC地…

贪心(基础算法)--- 区间选点

905. 区间选点 思路 &#xff08;贪心&#xff09;O(nlogn) 根据右端点排序 将区间按右端点排序 遍历区间&#xff0c;如果当前区间左端点不包含在前一个区间中&#xff0c;则选取新区间&#xff0c;所选点个数加1&#xff0c;更新当前区间右端点。如果包含&#xff0c;则跳…

雅特力AT32L021首款低功耗MCU震撼登场

雅特力于2月28日正式发布AT32L021首款入门级低功耗MCU&#xff0c;搭配不同容量Flash、SRAM&#xff0c;提供7种封装类型共21个型号选择&#xff0c;最小封装面积仅3x3mm。为降低能耗&#xff0c;延长设备运作时间&#xff0c;AT32L021系列支持多种能耗模式和休眠模式&#xff…

韦东山嵌入式Liunx入门驱动开发五

文章目录 一、驱动程序基石1-1 休眠与唤醒1-2 POLL机制1-3 异步通知(1) 异步通知程序解析(2) 异步通知机制内核代码详解 1-4 阻塞与非阻塞1-5 定时器(1) 内核函数(2) 定时器时间单位 1-6 中断下半部 tasklet 本人学习完韦老师的视频&#xff0c;因此来复习巩固&#xff0c;写以…

【活动】前端世界的“祖传代码”探秘:从古老魔法到现代重构

作为一名前端工程师&#xff0c;我时常在项目中邂逅那些被岁月打磨过的“祖传代码”。它们就像古老的魔法书页&#xff0c;用HTML标签堆砌起的城堡、CSS样式表中的炼金术&#xff0c;以及JavaScript早期版本中舞动的符咒。这些代码承载着先驱们的探索精神和独特智慧&#xff0c…

#FPGA(基础知识)

1.IDE:Quartus II 2.设备&#xff1a;Cyclone II EP2C8Q208C8N 3.实验&#xff1a;正点原子-verilog基础知识 4.时序图&#xff1a; 5.步骤 6.代码&#xff1a;

专业145+总分410+西工大西北工业大学827信号与系统考研经验电子信息与通信工程,海航,真题,大纲,参考书。

经过一年的努力&#xff0c;分数终于出来。今年专业课827信号与系统145&#xff08;很遗憾差了一点点满分&#xff0c;没有达到Jenny老师的最高要求&#xff09;&#xff0c;数一130&#xff0c;英语和政治也都比较平衡&#xff0c;总分410分&#xff0c;当然和信息通信考研Jen…

【Git】深入理解 Git 分支合并操作:git merge dev 命令详解

深入理解 Git 合并操作&#xff1a;git merge dev 命令详解 摘要&#xff1a;本文将深入探讨 Git 中的合并操作&#xff0c;以及如何使用 git merge dev 命令将dev 分支的修改合并到当前分支&#xff08;假设当前分支为main 分支&#xff09;中。通过详细的解释和示意图&#x…

linux安全--DNS欺骗,钓鱼网站搭建

目录 一&#xff0c;实验准备 首先让client能上网 1&#xff09;实现全网互通&#xff0c;实现全网互通过程请看 2&#xff09;SNAT源地址转换 3&#xff09;部署DHCP服务 4)配置DHCP服务 5&#xff09;启动服务 6&#xff09;安装DNS服务 7&#xff09;DNS配置 8)启动DNS…

HOOPS Communicator对3D大模型轻量化加载与渲染的4种解决方案

今天给大家介绍一些关于3D Web轻量化引擎HOOPS Commuicator的关键概念&#xff0c;这些概念可以帮您在HOOPS Communicator流缓存服务器之上更好地构建您自己的模型流服务器。如果您是有大型数据集&#xff0c;那么&#xff0c;使用流缓存服务器可以极大地帮助您最大限度地减少内…

Unity 预制体与变体

预制体作用&#xff1a; 更改预制体&#xff0c;则更改全部的以预制体复制出的模型。 生成预制体&#xff1a; 当你建立好了一个模型&#xff0c;从层级拖动到项目中即可生成预制体。 预制体复制模型&#xff1a; 将项目中的预制体拖动到层级中即可复制。或者选择物体复制粘贴。…

Java基础 - 6 - 面向对象(二)

Java基础 - 6 - 面向对象&#xff08;一&#xff09;-CSDN博客 二. 面向对象高级 2.1 static static叫做静态&#xff0c;可以修饰成员变量、成员方法 2.1.1 static修饰成员变量 成员变量按照有无static修饰&#xff0c;分为两种&#xff1a;类变量、实例变量&#xff08;对象…

VL53L8CX驱动开发(1)----驱动TOF进行区域检测

VL53L8CX驱动开发----1.驱动TOF进行区域检测 概述视频教学样品申请源码下载主要特点硬件准备技术规格系统框图应用示意图区域映射生成STM32CUBEMX选择MCU 串口配置IIC配置LPn 设置X-CUBE-TOF1串口重定向代码配置Tera Term配置演示结果 概述 VL53L8CX是一款8x8多区域ToF测距传感…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--强化学习

专属领域论文订阅 关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新论文。 分类: 大语言模型LLM视觉模型VLM扩散模型视觉…

Git分布式版本控制系统——git学习准备工作

一、Git仓库介绍 开发者可以通过Git仓库来存储和管理文件代码&#xff0c;Git仓库分为两种&#xff1a; 本地仓库&#xff1a;开发人员自己电脑上的Git仓库 远程仓库&#xff1a;远程服务器上的Git仓库 仓库之间的运转如下图&#xff1a; commit&#xff1a;提交&#xff…