嵌入式每天十条笔记(1)24-0222 C++学习

1.C++何时应该使用new,以及何时可以避免使用它

在C++中,你需要使用new关键字来分配堆内存(动态内存)为对象或基本数据类型分配空间。当你需要控制对象的生命周期,或者大小在编译时无法确定时,使用new是必要的。然而,使用new会引入内存管理的责任,你需要确保每次使用new分配的内存被delete释放,以避免内存泄漏。

这里有几种情景,分别描述何时应该使用new,以及何时可以避免使用它:

何时使用new

  1. 需要在多个函数调用中保持对象状态:如果你的对象需要在函数调用之间保持状态,且不应局限于栈的生命周期,则应使用new在堆上分配内存。

  2. 大型对象或数组:如果你需要分配大型的数组或对象,放在栈上可能会导致栈溢出,因此应该使用new在堆上分配。

  3. 变量大小的数组:如果数组的大小在编译时无法确定,则需要使用new在运行时分配所需内存。

  4. 对象的多态行为:如果你需要在运行时决定对象的确切类型(例如基于某种条件创建不同子类的实例),则需要使用指向基类的指针来分配具有多态行为的派生类实例。

  5. 对象生命周期管理:如果你想手动控制对象的生命周期,使用newdelete能够让你精确控制对象何时被创建和销毁。

何时不使用new

  1. 自动存储期的对象:如果对象的使用限制在一个块的范围内,则不需要使用new。可以在栈上创建对象,它会在离开作用域时自动被销毁。

  2. 临时对象:对于只在函数内部使用的临时对象,直接在栈上创建即可,无需使用new

  3. 异常安全性:在栈上创建对象通常更具异常安全性,如果异常发生,所有栈上的对象都会适时地被析构。

  4. 包含对象的区域:如果对象的全部或部分生命周期被另一个对象包含,通常可以在包含它的对象内部使用成员对象而不是指针。

  5. 智能指针:如果决定在堆上分配对象,应该考虑使用智能指针(如std::unique_ptrstd::shared_ptr)来管理资源,它们会自动管理对象生命周期,避免忘记手动delete

在现代C++编程中,建议尽量避免裸newdelete,转而使用标准库容器(如std::vectorstd::string)来管理资源,或使用智能指针来自动处理资源的释放。这样可以避免内存泄漏,简化程序,使程序更加健壮。

2.用delete释放内存,避免内存泄漏

在这里插入图片描述
在这里插入图片描述

3.C++的强制类型转换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.面向对象程序设计思想有三大特征:封装、继承和多态。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.权限控制符

在这里插入图片描述

7.在C++里,对于一个类的成员变量,如果在其中一个成员函数里被改变值了,那在调用另一个函数时,成员变量的值是什么?

在C++中,类的成员变量的值在不同成员函数之间是共享的。如果一个成员函数修改了类的成员变量的值,那么这个修改会影响该类的所有成员函数对该成员变量的访问。

举例说明:

#include <iostream>

class MyClass {
public:
    int myValue;

    void setValue(int value) {
        myValue = value;
    }

    void printValue() {
        std::cout << "myValue: " << myValue << std::endl;
    }
};

int main() {
    MyClass obj;
    obj.myValue = 5;
    obj.printValue(); // 输出: myValue: 5

    obj.setValue(10);
    obj.printValue(); // 输出: myValue: 10

    return 0;
}

在上述示例中,MyClass类有一个成员变量myValue,并有两个成员函数setValueprintValue。在main函数中,先设置obj对象的myValue为5,然后调用setValue函数将其值设置为10,最后再次调用printValue函数打印myValue的值,结果会是10,因为第一个函数修改了myValue的值,而第二个函数访问的是修改后的值。

因此,在C++中,一个类的成员函数对其成员变量的修改是可见的,并影响其他成员函数对该成员变量的访问。

8.类的构造函数

C++中的每个类至少要有一个构造函数,如果类中没有定义构造函数,系统会提供一个默认的无参构造函数,默认的无参构造函数体也为空,不具有实际的初始化意义。

在这里插入图片描述

8.1 无参构造函数

 1  #include<iostream> 
 2  #include<iomanip> 
 3  using namespace std; 
 4 class Clock     //定义时钟类Clock 
 5  { 
 6  public: 
 7       Clock();      //声明无参构造函数 
 8       void showTime();   //声明显示时间的成员函数 
 9  private: 
 10      int _hour;     //声明表示小时的成员变量 
 11      int _min;      //声明表示分钟的成员变量 
 12      int _sec;      //声明表示秒的成员变量 
 13 }; 
 14 Clock::Clock()     //类外实现无参构造函数 
 15 { 
 16      _hour=0;      //初始化过程,将成员变量初始化为0 
 17      _min=0; 
 18      _sec=0; 
 19 } 
 20 void Clock::showTime()   //类外实现成员函数 
 21 { 
 22      cout<<setw(2)<<setfill('0')<<_hour<<":" 
 23       <<setw(2)<<setfill('0')<<_min<<":" 
 24       <<setw(2)<<setfill('0')<<_sec<<endl; 
 25 } 
 26 int main() 
 27 { 
 28      Clock clock;     //创建对象clock 
 29      cout<<"clock:"; 
 30      clock.showTime();    //通过对象调用成员函数showTime()显示时间 
 31      return 0; 
 32 }

8.2 有参构造函数

 1  #include<iostream> 
 2  #include<iomanip> 
 3  using namespace std; 
 4 class Clock         //定义时钟类Clock 
 5  { 
 6  public: 
 7       Clock(int hour, int min, int sec);    //声明有参构造函数 
 8       void showTime();       //用于显示时间的成员函数 
 9  private: 
 10      int _hour;         //声明表示小时的成员变量 
 11      int _min;         //声明表示分钟的成员变量 
 12     int _sec;         //声明表示秒的成员变量 
 13 }; 
 14 Clock::Clock(int hour, int min, int sec)   //类外实现有参构造函数 
 15 { 
 16      _hour=hour;        //初始化过程,将初始值直接赋值给成员变量 
 17      _min=min; 
 18      _sec=sec; 
 19 } 
 20 void Clock::showTime()       //类外实现成员函数 
 21 { 
 22      cout<<setw(2)<<setfill('0')<<_hour<<":" 
 23       <<setw(2)<<setfill('0')<<_min<<":" 
 24       <<setw(2)<<setfill('0')<<_sec<<endl; 
 25 } 
 26 int main() 
 27 { 
 28      Clock clock1(10,20,30);       //创建对象clock1,传入初始值 
 29      cout<<"clock1:"; 
 30      clock1.showTime();        //通过对象调用成员函数showTime()显示时间 
 31      Clock clock2(22,16,12);       //创建对象clock2,传入初始值 
 32      cout<<"clock2:"; 
 33      clock2.showTime();        //通过对象调用成员函数showTime()显示时间 
 34      return 0; 
 35 }

9.含有成员对象的类的构造函数

 1  #include<iostream> 
 2  using namespace std; 
 3 class Birth       //定义出生日期类Birth 
 4  { 
 5  public: 
 6       Birth(int year,int month, int day); //构造函数 
 7       void show();       //声明成员函数show()显示日期 
 8  private: 
 9       int _year;  
 10      int _month; 
 11      int _day; 
 12 };
 13 //类外实现构造函数 
 14 Birth::Birth(int year, int month, int day) 
 15      :_year(year),_month(month),_day(day) 
 16 { 
 17      cout<<"Birth类构造函数"<<endl; 
 18 } 
 19 //类外实现show()函数 
 20 void Birth::show() 
 21 { 
 22      cout<<"出生日期:"<<_year<<"-"<<_month<<"-"<<_day<<endl; 
 23 } 
 24 class Student       //定义学生类Student 
 25 { 
 26 public: 
 27      //构造函数 
 28      Student(string name, int id, int year, int month, int day);  
 29      void show(); 
 30 private: 
 31      string _name; 
 32      int _id; 
 33      Birth birth; 
 34 }; 
 35 //类外实现构造函数 
 36 Student::Student(string name, int id, int year, int month, int day) 
 37      :birth(year,month,day) 
 38 { 
 39      cout<<"Student类构造函数"<<endl; 
 40      _name=name; 
 41      _id=id; 
 42 } 
 43 //类外实现show()函数 
 44 void Student::show() 
 45 { 
 46      cout<<"姓名:"<<_name<<endl; 
 47      cout<<"学号:"<<_id<<endl; 
 48      birth.show(); 
 49 } 
 50 int main() 
 51 { 
 52      Student stu("lili",10002,2000,1,1); //创建学生对象stu 
 53      stu.show();      //显示学生信息 
 54      return 0; 
 55 }

10.析构函数(释放类的资源)

在这里插入图片描述
在这里插入图片描述

 1  #define _CRT_SECURE_NO_WARNINGS 
 2  #include<iostream> 
 3  using namespace std; 
 4 class Rabbit        //定义兔子类Rabbit 
 5  { 
 6  public: 
 7       Rabbit(string name,const char* pf);  //声明构造函数 
 8       void eat(); 
 9       ~Rabbit();        //声明析构函数 
 10 private: 
 11      string _name;        //声明表示兔子名字的成员变量
 12      char* _food;        //声明表示兔子食物的成员变量 
 13 }; 
 14 Rabbit::Rabbit(string name, const char* pf) 
 15 { 
 16      cout<<"调用构造函数"<<endl; 
 17      _name=name; 
 18      _food=new char[50];      //为_food指针申请空间 
 19      memset(_food,0,50);      //初始化_food空间 
 20      strcpy(_food,pf);       //将参数pf指向的数据复制到_food中 
 21 } 
 22 void Rabbit::eat() 
 23 {          //类外实现成员函数 
 24      cout<<_name<<" is eating "<<_food<<endl; 
 25 } 
 26 Rabbit::~Rabbit()       //类外实现析构函数 
 27 { 
 28      cout<<"调用析构函数,析构"<<_name<<endl; 
 29      if(_food != NULL) 
 30           delete []_food; 
 31 } 
 32 int main() 
 33 { 
 34      Rabbit A("A","luobo"); 
 35      A.eat(); 
 36      Rabbit B("B","baicai"); 
 37      B.eat(); 
 38      return 0; 
 39 }

10const常成员变量

在这里插入图片描述

在这里插入图片描述

11.const常成员函数

在这里插入图片描述

12.Static修饰成员变量和成员函数

在这里插入图片描述
在这里插入图片描述

 1  #include<iostream> 
 2  using namespace std; 
 3  class Student            //定义学生类Student 
 4  { 
 5  public: 
 6       Student(string name);    //声明有参构造函数 
 7       ~Student();      //声明析构函数 
 8       static int _sum;     //声明表示学生总数的静态成员变量 
 9  private: 
 10     string _name;       //声明表示学生姓名的成员变量 
 11 }; 
 12 //类外实现Student类有参构造函数 
 13 Student::Student(string name) 
 14 { 
 15     this->_name=name; 
 16     _sum++;    
 17 } 
 18 Student::~Student(){}     //类外实现析构函数 
 19 int Student::_sum = 0;     //类外初始化静态成员变量_sum 
 20 int main() 
 21 { 
 22     Student stu1("张三"); 
 23     Student stu2("李四"); 
 24     cout<<"人数是:"<<stu1._sum<<endl;   //通过对象访问静态成员变量 
 25     cout<<"人数是:"<<stu2._sum<<endl; 
 26      cout<<"人数是"<<Student::_sum<<endl; //通过类访问静态成员变量 
 27      cout<<"stu1的大小是:"<<sizeof(stu1)<<endl; 
 28     return 0; 
 29 }

在这里插入图片描述

 1  #include<iostream> 
 2  #include<math.h> 
 3  using namespace std; 
 4 class Point         //定义坐标点类Point 
 5  { 
 6  public: 
 7      Point(float x,float y); 
 8      ~Point(); 
 9      static float getLen(Point& p1,Point& p2);    //声明静态成员函数 
 10     static float _len;        //声明静态成员变量_len 
 11 private: 
 12     float _x; 
 13     float _y; 
 14 }; 
 15 float Point::_len=0; 
 16 Point::Point(float x=0,float y=0):_x(x),_y(y)    //类外实现有参构造函数 
 17 { 
 18     cout<<"初始化坐标点"<<endl; 
 19 } 
 20 Point::~Point(){} 
 21 float Point::getLen(Point &p1,Point &p2)     //类外实现有参构造函数 
 22 { 
 23     float x=abs(p1._x-p2._x); 
 24     float y=abs(p1._y-p2._y); 
 25     _len=sqrtf(x*x+y*y); 
 26     return _len; 
 27 } 
 28 int main() 
 29 { 
 30     Point p1(1,2); 
 31     Point p2(6,8); 
 32     cout<<Point::getLen(p1,p2)<<endl; 
 33     return 0; 
 34 } 

在这里插入图片描述

13.const和static不用在c++的类里去定义成员变量和成员函数,而是用在c里有什么作用?

在C语言中,conststatic修饰符用于变量和函数,具有以下意义:

const修饰符:

  1. 常量声明:通过使用const关键字修饰变量,可以将其声明为常量,即不可修改的值。这样可以在代码中定义常量,并且能够防止意外修改变量值,提高代码的可读性和可维护性。
  2. 编译时常量:使用const修饰的变量在编译时可以被当做常量进行优化,例如将其内联到代码中或进行常量折叠等。

示例:

const int MAX_VALUE = 100; // 声明一个常量
const float PI = 3.14; // 声明一个常量

int main() {
    const int x = 5; // 声明并初始化一个常量
    // x = 10; // 错误,常量不可修改

    int array[MAX_VALUE]; // 使用常量作为数组大小

    const int *ptr = &x; // 声明一个指向常量的指针
    // *ptr = 7; // 错误,不可通过指针修改常量的值

    return 0;
}

static修饰符:

  1. 文件作用域:在全局变量和函数声明之前使用static关键字,可以将其作用域限制在当前文件中,避免与其他文件中的同名变量或函数产生冲突。
  2. 静态局部变量:在函数内部使用static关键字修饰局部变量,可以将其生命周期延长到整个程序的执行期间,并且在函数多次调用时保持其值不变。
  3. 静态函数:使用static关键字修饰函数,可以将其限制在当前文件中的可见性,只能在当前文件内部调用,无法被其他文件访问,起到了信息隐藏和封装的作用。

示例:

static int globalVar = 10; // 声明一个全局静态变量

void foo() {
    static int count = 0; // 静态局部变量
    count++;
    printf("Count: %d\n", count);
}

static void bar() { // 声明一个静态函数
    printf("This is a static function\n");
}

int main() {
    foo(); // 输出 Count: 1
    foo(); // 输出 Count: 2
    bar(); // 函数可直接调用

    return 0;
}

总的来说,conststatic在C语言中的用法可以提供更好的代码控制和可读性,用于定义常量、限制变量的可修改性、将变量或函数的作用域限定在当前文件中等。它们是C语言中常用的修饰符。

14.普通函数、类成员函数作为“类的友元函数”

在这里插入图片描述

 1  #include<iostream> 
 2  using namespace std; 
 3  class Circle 
 4  { 
 5  friend void getArea(Circle &circle);    //声明普通函数getArea()为友元函数 
 6  private: 
 7      float _radius; 
 8      const float PI=3.14; 
 9  public: 
 10     Circle(float radius); 
 11     ~Circle(); 
 12 }; 
 13 Circle::Circle(float radius=0):_radius(radius) 
 14 { 
 15     cout<<"初始化圆的半径为:"<<_radius<<endl; 
 16 } 
 17 Circle::~Circle(){} 
 18 void getArea(Circle &circle) 
 19 { 
 20      //访问类中的成员变量 
 21     cout<<"圆的半径是:"<<circle._radius<<endl; 
 22     cout<<"圆的面积是"<<circle.PI*circle._radius*circle._radius<<endl; 
 23     cout<<"友元函数修改半径:"<<endl; 
 24     circle._radius=1; 
 25     cout<<"圆的半径是:"<<circle._radius<<endl; 
 26 }  
 27 int main() 
 28 { 
 29     Circle circle(10); 
 30     getArea(circle); 
 31     return 0; 
 32 } 

在这里插入图片描述


 1  #include<iostream> 
 2  #include<math.h> 
 3  using namespace std; 
 4  class Point; 
 5  class Circle 
 6  {
 7  public: 
 8      float getArea(Point &p1,Point &p2);   //声明计算面积的成员函数 
 9  private: 
 10     const float PI=3.14; 
 11 }; 
 12 class Point 
 13 { 
 14 //声明类Circle的成员函数getArea()为友元函数 
 15 friend float Circle::getArea(Point &p1,Point &p2);   
 16 public: 
 17     Point(float x,float y); 
 18     ~Point(); 
 19 private: 
 20     float _x; 
 21     float _y; 
 22 }; 
 23 Point::Point(float x=0,float y=0):_x(x),_y(y)  //实现Point类的构造函数 
 24 { 
 25     cout<<"初始化坐标点"<<endl; 
 26 } 
 27 Point::~Point(){} 
 28 float Circle::getArea(Point &p1,Point &p2) 
 29 { 
 30     double x=abs(p1._x-p2._x);      //获取横轴坐标间的距离 
 31     float y=abs(p1._y-p2._y);     //获取纵轴坐标间的距离 
 32     float len=sqrtf(x*x+y*y);    //计算两个坐标点之间的距离 
 33     cout<<"获取两个坐标点之间的距离是"<<len<<endl; 
 34     return len*len*PI;       //友元函数访问私有成员变量PI 
 35 } 
 36 int main() 
 37 { 
 38     Point p1(5,5); 
 39     Point p2(10,10); 
 40     Circle circle; 
 41     float area=circle.getArea(p1,p2); 
 42     cout<<"圆的面积是:"<<area<<endl; 
 43     return 0; 
 44 } 

15 友元类

在这里插入图片描述


 1  #include<iostream> 
 2  using namespace std; 
 3 class Time        //定义Time类,描述时分秒 
 4  { 
 5  public: 
 6      Time(int hour, int minute, int second);   //声明有参构造函数 
 7      friend class Date;        //声明类Date为友元类 
 8  private: 
 9      int _hour, _minute, _second; 
 10 }; 
 11 class Date        //定义Date类 
 12 { 
 13 public: 
 14      Date(int year, int month, int day);   //声明有参构造函数 
 15      void showTime(Time& time);      //声明显示时间的成员函数 
 16 private: 
 17      int _year, _month, _day; 
 18 }; 
 19 Date::Date(int year, int month, int day)    //实现Date类构造函数 
 20 { 
 21      _year = year; 
 22      _month = month; 
 23      _day = day; 
 24 } 
 25 void Date::showTime(Time& time) 
 26 { 
 27      cout << _year << "-" << _month << "-" << _day 
 28       << " " << time._hour << ":" << time._minute 
 29       << ":" << time._second << endl; 
 30 } 
 31 Time::Time(int hour,int minute,int second)   //实现Time类构造函数 
 32 { 
 33      _hour = hour; 
 34      _minute = minute; 
 35      _second = second; 
 36 } 
 37 int main() 
 38 { 
 39      Time time(17,30,20);      //创建Time对象 
 40      Date date(2019,10,31);       //创建Date对象 
 41      date.showTime(time);      //调用showTime()显示年月日、时分秒信息 
 42      return 0; 
 43 }

16.运算符重载

在这里插入图片描述
在这里插入图片描述

 1  #include<iostream> 
 2  using namespace std; 
 3  class A 
 4  { 
 5  private: 
 6       int _x; 
 7       int _y; 
 8  public: 
 9       A(int x=0,int y=0):_x(x),_y(y){} 
 10      void show() const;               //输出数据 
 11      A operator+(const A& a) const;   //重载"+"运算符 
 12      A operator-(const A& a) const;   //重载"-"运算符 
 13      }; 
 14      void A::show() const      //show()函数的实现 
 15      { 
 16           cout<<"(_x,_y)="<<"("<<_x<<","<<_y<<")"<<endl; 
 17      } 
 18      A A::operator+(const A& a) const    //重载"+"运算符的实现 
 19      { 
 20           return A(_x+a._x,_y+a._y); 
 21      } 
 22      A A::operator-(const A& a) const    //重载"-"运算符的实现 
 23      { 
 24           return A(_x-a._x,_y-a._y); 
 25      } 
 26      int main() 
 27      { 
 28           A a1(1,2); 
 29           A a2(4,5); 
 30           A a; 
 31           cout<<"a1: ";  
 32          a1.show(); 
 33           cout<<"a2: ";  
 34          a2.show(); 
 35           a=a1+a2;        //实现两个对象相加 
 36           cout<<"a: ";  
 37          a.show(); 
 38           a=a1-a2;        //实现两个对象相减 
 39           cout<<"a: ";  
 40          a.show(); 
 41           return 0; 
 42      } 

在这里插入图片描述

17.继承

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

 1  #include<iostream> 
 2  using namespace std; 
 3 class Student       //定义学生类Student 
 4  { 
 5  public: 
 6 void setGrade(string grade);    //设置年级的成员函数 
 7 string getGrade();      //获取年级的成员函数 
 8 void setName(string name);    //设置姓名的成员函数 
 9 string getName();      //获取姓名的成员函数 
 10 protected: 
 11      string _grade;      //保护成员:表示年级 
 12 private: 
 13      string _name;       //私有成员:表示姓名 
 14 }; 
 15 void Student::setGrade(string grade)   //类外实现setGrade()函数 
 16 { 
 17      _grade=grade; 
 18 } 
 19 string Student::getGrade()    //类外实现getGrade()函数 
 20 { 
 21      return _grade; 
 22 } 
 23 void  Student::setName(string name)  //类外实现setName()函数 
 24 { 
 25      _name=name; 
 26 } 
 27 string Student::getName()    //类外实现getName()函数 
 28 { 
 29      return _name; 
 30 } 
 31 class Undergraduate:public Student  //大学生类公有继承学生类 
 32 { 
 33 public: 
 34      Undergraduate(string major);    //声明构造函数 
 35      void show();       //声明显示大学生信息的成员函数 
 36 private: 
 37      string _major;      //私有成员:表示专业 
 38 }; 
 39 //类外实现构造函数 
 40 Undergraduate::Undergraduate(string major) 
 41 { 
 42      _major=major; 
 43 } 
 44 void Undergraduate::show()    //类外实现show()函数 
 45 { 
 46      cout<<"姓名:"<<getName()<<endl;   //派生类调用基类成员函数 
 47      cout<<"年级:"<<_grade<<endl;   //派生类访问继承的基类成员变量 
 48      cout<<"专业:"<<_major<<endl;   //派生类访问新增成员 
 49 } 
 50 int main() 
 51 { 
 52      //创建大学生类对象stu 
 53      Undergraduate stu("计算机信息工程");  
 54      stu.setGrade("大三");    //派生类对象调用基类成员函数设置年级 
 55      stu.setName("zhangsan");    //派生类对象调用基类成员函数设置姓名 
 56      stu.show();      //派生类对象调用新增成员函数显示学生信息 
 57      return 0; 
 58 }

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值