C++基本学习手册(大部分为chatgpt提供源码)

  • 1、类和对象

    • 构造函数:用于初始化
    • 析构函数:用于销毁对象,释放内存
      • 析构函数是C++类中的一种特殊函数,用于在对象生命周期结束时执行一些清理工作。析构函数的名称与类名相同,前面加上波浪号 ~。它在对象被销毁时自动调用。
      • class MyClass {
        public:
        // 构造函数
        MyClass() {
        // 构造函数的初始化逻辑
        std::cout << "Constructor called!" << std::endl;
        }
        // 析构函数
        ~MyClass() {
        // 析构函数的清理逻辑
        std::cout << "Destructor called!" << std::endl;
        }
        };
        int main() {
        {
        MyClass obj; // 在这个作用域内创建对象
        } // 对象超出作用域,析构函数被调用
        return 0;
        }

    • 拷贝构造函数:用于拷贝
      • 拷贝构造函数是C++中的一种特殊构造函数,用于在创建对象时以另一个同类型对象的值进行初始化。它的目的是创建一个新对象,该对象的值与给定对象相同。
        #include <iostream>
        class MyClass {
        public:
        // 构造函数
        MyClass(int value) : data(value) {
        std::cout << "Constructor called." << std::endl;
        }
        // 拷贝构造函数
        MyClass(const MyClass& other) : data(other.data) {
        std::cout << "Copy constructor called." << std::endl;
        }
        // 其他成员函数
        int getData() const {
        return data;
        }
        private:
        int data;
        };
        int main() {
        // 创建对象 obj1
        MyClass obj1(42);
        // 使用拷贝构造函数创建对象 obj2,并将其值初始化为 obj1 的值
        MyClass obj2 = obj1;
        // 输出结果
        std::cout << "obj1 data: " << obj1.getData() << std::endl;
        std::cout << "obj2 data: " << obj2.getData() << std::endl;
        return 0;
        }

    • 友元函数:定义时候可以不加::
      • 友元函数是一个在类的声明中用 friend 关键字声明的非成员函数。友元函数可以访问该类的私有成员,即使它不是该类的成员函数。这使得友元函数能够与类进行协作,而不受类的封装性的限制。
        class MyClass {
        private:
        int privateMember;
        public:
        MyClass(int value) : privateMember(value) {}
        friend void friendFunction(const MyClass& obj);
        };
        // 在类外定义友元函数
        void friendFunction(const MyClass& obj) {
        std::cout << "Friend function accessing private member: " << obj.privateMember << std::endl;
        }
        int main() {
        MyClass obj(42);
        friendFunction(obj);
        return 0;
        }

    • 内联函数:一般用于代码量比较小的函数,不执行调用,直接替换
      • inline:内联函数是C++中的一种优化手段,用于在编译器决定是否将函数调用替换为函数体的代码。通过将函数的定义放在类声明中(通常在头文件中),编译器可以选择性地内联函数调用,而不是生成函数调用的指令。
    • this指针:this->data等效为(*this).data
      • 在C++中,this 指针是一个特殊的指针,它指向当前对象的地址。它是每个非静态成员函数的隐式参数,用于指向调用该函数的对象。通过 this 指针,可以在成员函数内部访问对象的成员变量和其他成员函数。
        #include <iostream>
        class MyClass {
        public:
        // 成员变量
        int data;
        // 成员函数
        void setData(int value) {
        // 使用 this 指针访问对象的成员变量
        this->data = value;
        }
        void displayData() {
        // 使用 this 指针访问对象的成员函数
        std::cout << "Data: " << this->getData() << std::endl;
        }
        private:
        int getData() const {
        // 在成员函数内部使用 this 指针可以访问私有成员
        return this->data;
        }
        };
        int main() {
        MyClass obj1, obj2;
        // 使用 this 指针在对象上调用成员函数
        obj1.setData(42);
        obj1.displayData();
        // this 指针在不同对象上的值是不同的
        obj2.setData(99);
        obj2.displayData();
        return 0;
        }
    • C++类的静态成员
      • 在C++中,类的静态成员是与类关联而不是与类的实例(对象)关联的成员。静态成员属于整个类而不是类的实例,并且在类的所有实例之间共享。通过使用 static 关键字来声明和定义静态成员。
        #include <iostream>
        class MyClass {
        public:
        // 静态成员变量
        static int staticData;
        // 静态成员函数
        static void staticFunction() {
        std::cout << "Static function called." << std::endl;
        }
        // 普通成员函数
        void displayStaticData() {
        // 在成员函数中访问静态成员变量
        std::cout << "Static data: " << staticData << std::endl;
        }
        };
        // 初始化静态成员变量
        int MyClass::staticData = 0;
        int main() {
        // 访问静态成员变量和静态成员函数
        std::cout << "Initial static data: " << MyClass::staticData << std::endl;
        MyClass::staticFunction();
        // 创建类的实例
        MyClass obj1;
        MyClass obj2;
        // 通过实例访问静态成员变量和静态成员函数
        obj1.displayStaticData();
        obj2.staticFunction();
        // 修改静态成员变量的值
        obj1.staticData = 42;
        // 通过不同实例访问静态成员变量
        std::cout << "Static data from obj1: " << obj1.staticData << std::endl;
        std::cout << "Static data from obj2: " << obj2.staticData << std::endl;
        return 0;
        }

  • 2、C++继承

    • C++中的继承是一种面向对象编程的重要概念,它允许一个类(派生类)获得另一个类(基类)的属性和行为。在继承中,派生类可以重用基类的成员(数据成员和成员函数),并且可以在其基础上添加新的成员或修改继承的成员。
      #include <iostream>
      using namespace std;
      class shape
      {
      protected:
      double width;
      double heigth;
      public:
      void setWith(double w) { width = w; }
      void setHeight(double H) { heigth = H; }
      };
      class Rectanle : public shape
      {
      public:
      double getarea() { return width * heigth; }
      };
      int main()
      {
      Rectanle rect;
      rect.setHeight(3);
      rect.setWith(4);
      cout << rect.getarea() << endl;
      Rectanle* rect_1 = new Rectanle;
      rect_1->setHeight(5);
      rect_1->setWith(6);
      cout << rect_1->getarea() << endl;
      return 0;
      }

  • 3、C++重载

    • 函数重载是指在同一个作用域内定义多个具有相同名称但参数列表不同的函数。在C++中,函数重载允许你为一个特定的函数名定义多个版本,以应对不同的参数类型或参数个数。
      #include <iostream>
      // 函数重载
      int add(int a, int b) {
      return a + b;
      }
      double add(double a, double b) {
      std::cout << "add 1 " << std::endl;
      return a + b;
      }
      // 函数重载,参数个数不同
      int add(int a, int b, int c) {
      std::cout << "add 2 " << std::endl;
      return a + b + c;
      }
      double add(int a, int b, double c) {
      std::cout << "add 3 " << std::endl;
      return a + b + c;
      }
      int main() {
      // 调用不同版本的函数
      std::cout << "Sum (int): " << add(3, 4) << std::endl;
      std::cout << "Sum (double): " << add(3.5, 4.2) << std::endl;
      std::cout << "Sum (int, int, int): " << add(1, 2, 3) << std::endl;
      std::cout << "Sum (int, int, double): " << add(1, 2, 3.2) << std::endl;
      return 0;
      }

    • C++一元运算符重载:在C++中,一元运算符重载允许你重新定义类的一元运算符的行为。一元运算符是只有一个操作数的运算符,例如取地址运算符 &、逻辑非运算符 !、递增运算符 ++ 等。
      #include <iostream>
      class Counter {
      private:
      int count;
      public:
      Counter() : count(0) {}
      // 重载前缀递增运算符 ++
      Counter operator++() {
      ++count;
      return *this;
      }
      // 重载后缀递增运算符 ++
      Counter operator++(int) {
      Counter temp = *this;
      ++count;
      return temp;
      }
      int getCount() const {
      return count;
      }
      };
      int main() {
      Counter c1, c2;
      // 前缀递增
      ++c1;
      std::cout << "Counter c1: " << c1.getCount() << std::endl;
      // 后缀递增
      c2++;
      std::cout << "Counter c2: " << c2.getCount() << std::endl;
      return 0;
      }

    • C++二元运算符重载:在C++中,二元运算符重载允许你重新定义类对象之间的二元运算符的行为。二元运算符是有两个操作数的运算符,例如加法运算符 +、减法运算符 -、乘法运算符 * 等。
      return_type operator@(const MyClass& obj1, const MyClass& obj2);
       
      #include <iostream>
      using namespace std;
      class Box
      {
      double length; // Length of a box
      double breadth; // Breadth of a box
      double height; // Height of a box
      public:
      double getVolume()
      {
      return length * breadth * height;
      }
      void setLength(double len)
      {
      length = len;
      }
      void setBreadth(double bre)
      {
      breadth = bre;
      }
      void setHeight(double hei)
      {
      height = hei;
      }
      // Overload + operator to add two Box objects.
      Box operator+(const Box& b)
      {
      Box box;
      box.length = length + b.length;
      box.breadth = breadth + b.breadth;
      box.height = height + b.height;
      return box;
      }
      };
      // Main function for the program
      int main()
      {
      Box Box1; // Declare Box1 of type Box
      Box Box2; // Declare Box2 of type Box
      Box Box3; // Declare Box3 of type Box
      double volume = 0.0; // Store the volume of a box here
      // box 1 specification
      Box1.setLength(6.0);
      Box1.setBreadth(7.0);
      Box1.setHeight(5.0);
      // box 2 specification
      Box2.setLength(12.0);
      Box2.setBreadth(13.0);
      Box2.setHeight(10.0);
      // volume of box 1
      volume = Box1.getVolume();
      cout << "Volume of Box1 : " << volume << endl;
      // volume of box 2
      volume = Box2.getVolume();
      cout << "Volume of Box2 : " << volume << endl;
      // Add two object as follows:
      Box3 = Box1 + Box2;
      // volume of box 3
      volume = Box3.getVolume();
      cout << "Volume of Box3 : " << volume << endl;
      return 0;
      }
      
    • C++关系运算符重载:在C++中,关系运算符是用于比较两个对象之间关系的运算符,例如相等性运算符 ==、不等性运算符 !=、大于运算符 >、小于运算符 < 等。你可以通过重载这些运算符来定义类对象之间的关系。
      #include <iostream>
      class Point {
      private:
      int x;
      int y;
      public:
      Point(int px = 0, int py = 0) : x(px), y(py) {}
      // 重载相等性运算符 ==
      bool operator==(const Point& other) const {
      return (x == other.x) && (y == other.y);
      }
      // 输出点对象
      void display() const {
      std::cout << "(" << x << ", " << y << ")";
      }
      };
      int main() {
      Point p1(2, 3);
      Point p2(2, 3);
      Point p3(4, 5);
      // 使用重载的相等性运算符
      if (p1 == p2) {
      std::cout << "p1 is equal to p2." << std::endl;
      } else {
      std::cout << "p1 is not equal to p2." << std::endl;
      }
      if (p1 == p3) {
      std::cout << "p1 is equal to p3." << std::endl;
      } else {
      std::cout << "p1 is not equal to p3." << std::endl;
      }
      return 0;
      }
    • C++输入/输出运算符重载:在C++中,输入/输出运算符 >> 和 << 也可以被重载,以便你能够为自定义类定义输入和输出行为。这使得你可以使用标准输入流 (cin) 和标准输出流 (cout) 来处理自定义对象。
      #include <iostream>
      class Point {
      private:
      int x;
      int y;
      public:
      Point(int px = 0, int py = 0) : x(px), y(py) {}
      // 重载输入运算符 >>
      friend std::istream& operator>>(std::istream& is, Point& obj) {
      is >> obj.x >> obj.y;
      return is;
      }
      // 重载输出运算符 <<
      friend std::ostream& operator<<(std::ostream& os, const Point& obj) {
      os << "(" << obj.x << ", " << obj.y << ")";
      return os;
      }
      };
      int main() {
      Point p;
      // 从标准输入流读取点的坐标
      std::cout << "Enter x and y coordinates: ";
      std::cin >> p;
      // 输出点对象到标准输出流
      std::cout << "Point: " << p << std::endl;
      return 0;
      }

    • C++递增++和递减--重载
      #include <iostream>
      using namespace std;
      class Time
      {
      private:
      int hours; // 0 to 23
      int minutes; // 0 to 59
      public:
      // required constructors
      Time() {
      hours = 0;
      minutes = 0;
      }
      Time(int h, int m) {
      hours = h;
      minutes = m;
      }
      // method to display time
      void displayTime()
      {
      cout << "H: " << hours << " M:" << minutes << endl;
      }
      // overloaded prefix ++ operator
      Time operator++ ()
      {
      ++minutes; // increment this object
      if (minutes >= 60)
      {
      ++hours;
      minutes -= 60;
      }
      return Time(hours, minutes);
      }
      // overloaded postfix ++ operator
      Time operator++(int)
      {
      // save the orignal value
      Time T(hours, minutes);
      // increment this object
      ++minutes;
      if (minutes >= 60)
      {
      ++hours;
      minutes -= 60;
      }
      // return old original value
      return T;
      }
      };
      int main()
      {
      Time T1(11, 59), T2(10, 40);
      ++T1; // increment T1
      T1.displayTime(); // display T1
      ++T1; // increment T1 again
      T1.displayTime(); // display T1
      T2++; // increment T2
      T2.displayTime(); // display T2
      T2++; // increment T2 again
      T2.displayTime(); // display T2
      return 0;
      }

    • C++赋值运算符重载:可以重载赋值运算符(=),就像在其它运算符中,它可以被用来创建一个对象就像拷贝构造函数。
      #include <iostream>
      using namespace std;
      class Distance
      {
      private:
      int feet; // 0 to infinite
      int inches; // 0 to 12
      public:
      // required constructors
      Distance() {
      feet = 0;
      inches = 0;
      }
      Distance(int f, int i) {
      feet = f;
      inches = i;
      }
      void operator=(const Distance& D)
      {
      feet = D.feet;
      inches = D.inches;
      }
      // method to display distance
      void displayDistance()
      {
      cout << "F: " << feet << " I:" << inches << endl;
      }
      };
      int main()
      {
      Distance D1(11, 10), D2(5, 11);
      cout << "First Distance : ";
      D1.displayDistance();
      cout << "Second Distance :";
      D2.displayDistance();
      // use assignment operator
      D1 = D2;
      cout << "First Distance :";
      D1.displayDistance();
      return 0;
      }

    • C++函数调用运算符()重载:函数调用运算符()可以被重载用于类的对象。当重载(),不是创造一种新的方式来调用一个函数。相反,这是创建一个可以传递参数的任意数目的运算符功能。
      #include <iostream>
      using namespace std;
      class Distance
      {
      private:
      int feet; // 0 to infinite
      int inches; // 0 to 12
      public:
      // required constructors
      Distance() {
      feet = 0;
      inches = 0;
      }
      Distance(int f, int i) {
      feet = f;
      inches = i;
      }
      // overload function call
      Distance operator()(int a, int b, int c)
      {
      Distance D;
      // just put random calculation
      D.feet = a + c + 10;
      D.inches = b + c + 100;
      return D;
      }
      // method to display distance
      void displayDistance()
      {
      cout << "F: " << feet << " I:" << inches << endl;
      }
      };
      int main()
      {
      Distance D1(11, 10), D2;
      cout << "First Distance : ";
      D1.displayDistance();
      D2 = D1(10, 10, 10); // invoke operator()
      cout << "Second Distance :";
      D2.displayDistance();
      return 0;
      }
    • C++下标[]运算符重载
      #include <iostream>
      using namespace std;
      const int SIZE = 10;
      class safearay
      {
      private:
      int arr[SIZE];
      public:
      safearay()
      {
      register int i;
      for (i = 0; i < SIZE; i++)
      {
      arr[i] = i;
      }
      }
      int& operator[](int i)
      {
      if (i > SIZE)
      {
      cout << "Index out of bounds" << endl;
      // return first element.
      return arr[0];
      }
      return arr[i];
      }
      };
      int main()
      {
      safearay A;
      cout << "Value of A[2] : " << A[2] << endl;
      cout << "Value of A[5] : " << A[5] << endl;
      cout << "Value of A[12] : " << A[12] << endl;
      return 0;
      }
    • C++类成员访问运算符(->)重载:类成员访问运算符(- >)可以被重载,但它较为麻烦。它被定义为一个类类型的一个“类指针”行为。操作符 ->必须是一个成员函数。如果使用,它的返回类型必须为指针或一个类的对象,才可以适用。
  • 4、C++多态

    • 多态性是面向对象编程的一个重要概念,它使得可以在不考虑对象具体类型的情况下调用方法。C++ 中的多态性主要通过虚函数(virtual function)和虚函数表(vtable)来实现。
      #include <iostream>
      // 基类
      class Shape {
      public:
      // 虚函数
      virtual void draw() const {
      std::cout << "Drawing a shape." << std::endl;
      }
      };
      // 派生类1
      class Circle : public Shape {
      public:
      // 重写基类的虚函数
      void draw() const override {
      std::cout << "Drawing a circle." << std::endl;
      }
      };
      // 派生类2
      class Square : public Shape {
      public:
      // 重写基类的虚函数
      void draw() const override {
      std::cout << "Drawing a square." << std::endl;
      }
      };
      int main() {
      Circle circle;
      Square square;
      // 使用基类指针,实现多态
      Shape* shape1 = &circle;
      Shape* shape2 = &square;
      // 调用虚函数,实际调用的是对象的类型的虚函数
      shape1->draw(); // 输出 "Drawing a circle."
      shape2->draw(); // 输出 "Drawing a square."
      return 0;
      }
    • 虚拟函数:虚函数是在使用关键字的虚拟声明的基类的函数。定义在基类中的虚函数,与其他版本在派生类不同,我们不希望这个函数静态链接编译器。我们所要的是函数的选择被调用在程序中任何给定的点是基于用于调用它的类的对象。这种操作被称为动态链接,或后期绑定。
    • 纯虚函数:纯虚函数是一个在基类中声明但没有实际实现的虚函数,通过将虚函数声明为纯虚函数,可以将基类设计为抽象类,强制派生类提供实现。
      #include <iostream>
      using namespace std;
      class Shape {
      public:
      virtual int area() = 0; // 纯虚函数声明
      };
      class Circle : public Shape {
      public:
      int area() override {
      // 提供 area 的实现
      return 0;
      }
      };
      int main() {
      //Shape A;
      Circle myCircle; // 正确:可以实例化派生类
      return 0;
      }
  • 5、C++数据抽象

    • 数据抽象是一种面向对象编程中的概念,它将类的实现细节隐藏在类的接口之后,使得用户只能通过公共接口来访问类的成员和方法。这有助于实现封装、简化复杂性和提高代码的可维护性。
    • C++数据封装:封装是面向对象编程中的另一个概念,它与数据抽象密切相关。封装是将类的实现细节隐藏在类的私有部分,只暴露必要的公共接口。
    • C++接口(抽象类):在C++中,接口通常通过抽象类来实现。抽象类是包含纯虚函数的类,它定义了一组接口方法,但没有提供这些方法的实现。派生类必须提供这些纯虚函数的实现,以成为一个完整的类。抽象类的实例不能被创建,但可以作为指针或引用使用。
  • 6、C++文件和流

    • 在C++中,文件和流(stream)是用于进行输入和输出操作的关键概念。流是一种数据传输的抽象,可以从中读取数据(输入流)或向其中写入数据(输出流)。C++提供了一个丰富的文件和流库,可以用于与文件系统交互、进行数据输入和输出等操作。
    • 文件流类(fstream): C++提供了三个主要的文件流类:ifstream、ofstream 和 fstream。这些类分别用于输入、输出和同时进行输入输出。
      #include <fstream>

      // 以输入方式打开文件
      std::ifstream inputFile("example.txt");

      // 以输出方式打开文件
      std::ofstream outputFile("output.txt");

      // 以输入输出方式打开文件
      std::fstream inOutFile("data.txt");

    • 文件的打开和关闭: 使用文件流类的对象可以打开和关闭文件。打开文件时,可以指定文件名、打开模式等参数。
      // 打开文件
      inputFile.open("example.txt", std::ios::in);

      // 关闭文件
      inputFile.close();
    • 文件读写操作: 文件流对象可以使用类似于 >> 和 << 的运算符来进行输入和输出操作。
      // 从文件读取数据
      int number;
      inputFile >> number;
      // 向文件写入数据
      outputFile << "Hello, World!";
    • 错误检查: 在文件操作中,需要检查文件是否成功打开或关闭,以及是否发生了读写错误。
      if (inputFile.is_open()) {
      // 文件已成功打开
      } else {
      // 文件未成功打开
      }
      if (!outputFile.fail()) {
      // 写入操作成功
      } else {
      // 写入操作失败
      }
    • 文件位置指针: 文件流对象包含一个文件位置指针,它指示下一次读写操作将在文件中的位置。可以使用 seekg 和 seekp 函数进行位置指针的定位。
      // 设置读取位置为文件开头
      inputFile.seekg(0, std::ios::beg);
  • 7、C++异常处理

    • 异常处理是一种在程序执行期间检测和响应程序中出现的异常情况的机制。在C++中,异常处理通过 try、catch 和 throw 关键字来实现。
    • try 块: 在 try 块中放置可能引发异常的代码。
      try {
      // 可能引发异常的代码
      } catch (ExceptionType1 ex1) {
      // 处理 ExceptionType1 类型的异常
      } catch (ExceptionType2 ex2) {
      // 处理 ExceptionType2 类型的异常
      } catch (...) {
      // 处理其他类型的异常
      }
    • throw 语句: 使用 throw 语句引发异常。异常可以是任何类型,通常是某种类的实例
      throw MyException("An error occurred");
    • catch 块: 在 catch 块中处理异常。catch 块中的代码将在匹配到相应类型的异常时执行
      try {
      // 可能引发异常的代码
      } catch (MyException ex) {
      // 处理 MyException 类型的异常
      }
    • 异常类: 在C++中,异常通常是通过类来表示的。你可以定义自己的异常类,派生自 std::exception 类或其派生类。
      #include <stdexcept>
      class MyException : public std::exception {
      public:
      const char* what() const noexcept override {
      return "My custom exception";
      }
      };
    • 标准异常类: C++标准库提供了一些标准的异常类,如 std::runtime_error、std::logic_error 等。这些异常类派生自 std::exception,并提供了一些常见的异常类型。
      #include <stdexcept>
      try {
      // 可能引发异常的代码
      } catch (const std::runtime_error& ex) {
      // 处理 std::runtime_error 类型的异常
      } catch (const std::logic_error& ex) {
      // 处理 std::logic_error 类型的异常
      } catch (...) {
      // 处理其他类型的异常
      }
    • 异常规范: 异常规范是一种在函数声明中指定可能抛出的异常类型的方法。然而,C++11以后的版本不再推荐使用异常规范,而是更倾向于使用 noexcept 关键字。
      // 不推荐使用异常规范
      void myFunction() throw(MyException) {
      // 可能抛出 MyException 类型的异常
      }
      // 推荐使用 noexcept
      void myFunction() noexcept {
      // 不会抛出异常
      }
    • case
      #include <iostream>
      using namespace std;
      double division(int a, int b)
      {
      if (b == 0)
      {
      throw "Division by zero condition!";
      }
      return (a / b);
      }
      int main()
      {
      int x = 50;
      int y = 0;
      double z = 0;
      try {
      z = division(x, y);
      cout << z << endl;
      }
      catch (const char* msg) {
      cerr << msg << endl;
      }
      return 0;
      }
  • 8、C++动态内存

    • 在C++中,动态内存分配和释放是通过 new 和 delete 操作符来实现的。这允许程序在运行时动态地分配内存,以适应不同的需求。
    • 动态内存分配 (new): new 操作符用于在堆上动态地分配内存。它返回所分配内存的地址,并可以用于创建单个对象、数组或自定义类型的对象。
      // 分配单个整数的内存
      int* intPtr = new int;
      // 分配整数数组的内存
      int* intArray = new int[10];
      // 分配自定义类型对象的内存
      MyClass* obj = new MyClass;
    • 动态内存释放 (delete): delete 操作符用于释放通过 new 分配的内存。这是防止内存泄漏的关键步骤。
      // 释放单个整数的内存
      delete intPtr;
      // 释放整数数组的内存
      delete[] intArray;
      // 释放自定义类型对象的内存
      delete obj;
    • 动态内存分配失败的检查: 在分配动态内存时,应该检查内存是否成功分配。如果分配失败,new 操作符将抛出 std::bad_alloc 异常。
      try {
      int* intPtr = new int;
      } catch (const std::bad_alloc& ex) {
      // 处理内存分配失败异常
      std::cerr << "Memory allocation failed: " << ex.what() << std::endl;
      }
    • 动态内存的释放 (delete) 与空指针: 在使用 delete 操作符释放动态内存之后,最好将指针设置为 nullptr,以防止野指针的问题。
      delete intPtr;
      intPtr = nullptr; // 防止野指针
    • 智能指针: C++11 引入了智能指针,如 std::unique_ptr 和 std::shared_ptr,它们提供了更安全和方便的方式来管理动态内存,减少了手动管理内存的复杂性和错误。
      #include <memory>
      // 使用 std::unique_ptr 管理动态内存
      std::unique_ptr<int> intPtr = std::make_unique<int>();
  • 9、C++命名空间

    • 考虑这样一种情况,当我们使用相同的名称,叫Zara的两个人在同一个班级。我们需要明确区分它们将不得不使用一些额外的信息,如他们的名字,如他们生活在不同的区域或母亲或父亲的名字等等。同样的情况也出现在C++应用程序中。例如,可能会有一些代码,有一个函数调用xyz()函数,而且这也有同样的功能另一个某某库也有提供。现在,编译器没有办法知道xyz()函数指的是代码中的哪一个版本。命名空间被设计为克服这一困难,并作为附加信息来区分类似函数,类,变量等具有相同名称的不同的库可用。使用命名空间可以定义在名称定义的上下文。在本质上,一个命名空间中定义了一个范围。
      #include <iostream>
      using namespace std;
      // first name space
      namespace first_space 
      {
      void func() 
      {
          cout << "Inside first_space" << endl;
      }
      }
      // second name space
      namespace second_space 
      {
      void func() 
          {
              cout << "Inside second_space" << endl;
          }        
      }
      int main()
      {
          // Calls function from first name space.
          first_space::func();
          // Calls function from second name space.
          second_space::func();
          return 0;
      }
  • 10、C++模板

    • C++模板是一种将代码参数化的机制,允许程序员编写通用的、与数据类型无关的代码。模板是一种在编译时生成代码的方式,通过模板,你可以编写适用于不同数据类型的通用算法和数据结构。
    • 函数模板: 函数模板允许你编写一个通用的函数,可以处理多种数据类型。函数模板使用 template 关键字声明,通常包含一个或多个模板参数。
      template <typename T>
      T add(T a, T b) {
      return a + b;
      }
      int main() {
      int sum1 = add(3, 4); // 实例化为 add<int>(3, 4)
      double sum2 = add(1.5, 2.5); // 实例化为 add<double>(1.5, 2.5)
      return 0;
      }
    • 类模板: 类模板允许你编写通用的类,其中一个或多个类成员的类型由模板参数确定。
      template <typename T>
      class Pair {
      private:
      T first;
      T second;
      public:
      Pair(T a, T b) : first(a), second(b) {}
      T getFirst() const {
      return first;
      }
      T getSecond() const {
      return second;
      }
      };
      int main() {
      Pair<int> intPair(1, 2);
      Pair<double> doublePair(1.5, 2.5);
      return 0;
      }
    • 模板特化: 模板特化允许你为特定的模板参数提供特定的实现。
      // 通用模板
      template <typename T>
      T square(T x) {
      return x * x;
      }
      // 模板特化,提供 double 类型的特定实现
      template <>
      double square(double x) {
      return x * x;
      }
    • 模板函数与模板类的分离编译: 在大型项目中,可以将模板函数和模板类的声明与定义分开,以便提高代码的可维护性。
      // 模板声明放在头文件中(example.h)
      template <typename T>
      T add(T a, T b);
      // 模板定义放在源文件中(example.cpp)
      template <typename T>
      T add(T a, T b) {
      return a + b;
      }

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值