练习一

知识点1

  • const 修饰符 (用来表示常量, 不允许修改的值)
      1. 与 C语言中的 #define 作用相同, 均为定义常量, 但 const 更灵活, 安全性更高
      1. 支持基本数据类型的常量定义
        • 特点:
          • 不允许在任何地方进行修改
          • 优于 #define 的形式
          • 作为参数时, 可保证实参不会被改动/破坏 ( 编译时会提示你错误,导致整个程序无法运行)
            • image.png
      1. 可以与指针一起使用:
          1. 指向常量的指针
          • const char* pc = "abcd"; // 指向常量的指针
          • 含义: 声明了一个名为 pc 的指针变量, 指向的是字符型常量
            • 也就是你不能改变字符串本身的值
              • 即: 不可以使用数组方式将其中的某个字符换掉 pc[2] = "c";
            • 但是你可以把它整体都换了
              • 即: pc = "efgh";
          • 通俗来讲:
            • 你开垦了一个荒地, 里面已经种上了草莓, 你又想种西瓜了, 但是草莓还没熟, 你总不能把草莓毁了, 种西瓜吧.😂
          1. 常指针 (与上面相反, 地址不能变)
          • char* const pc = "abcd";
          • 含义: 声明了一个名为 pc 的指针变量, 指向的是字符型数据的常指针
            • 也就是你可以改变字符串本身的值
              • 即: 使用数组方式将其中的某个字符换掉 pc[2] = "c";
            • 但是你不可以把它整体的地址都换了
              • 即: 不可以pc = "efgh";
          • 通俗来讲:
            • 你只有一块土地, 里面已经种上了草莓, 你又想种西瓜了, 地里只能种一种水果, 所以你只能把草莓毁了,来 种西瓜.😂
          1. 指向常量的常指针
          • const char* const pc = "abcd";
          • 含义: 声明了一个名为 pc 的指针变量, 指向的是字符型常量的常指针
          • 即上述两种情况的不允许操作的行为的集合
            • 不允许通过数组改变原字符型数据本身的某一个或多个值
            • 不允许更改整体的地址
      • 来道习题练练手

        1.1

        image.png

  • 解析:

    • 首先定义代码中 变量类型char 前有一个 const 表示是一个指向字符型常量, 不能通过数据修改字符型数据的某个值
    • char* 表示他是一个指针
    • char* 后有一个const 表示是一个常指针, 则不能更改这个指针的地址
    • 那么啥都不能修改了, 就只能读取指针的内容了, 所以选 D 输出内容

      1.2

      image.png

  • char* 后有const , char 前没有, 所以不能修改指针地址, 但可以通过数组修改其中的内容, 所以选 A

    1.3

    image.png

  • char* 后没有const , char 前有, 所以只能修改指针地址, 不可以通过数组修改其中的内容, 所以 A 是错的

  • B : 为把整体修改了 (字符型数据在初始化时自动会开辟了一个地址供自己使用)
  • C D : new 即为开辟了一个多大的空间

    1.4

    image.png

练习二

知识点2

  • 重载函数:
    • 即: 两个或两个以上的函数, 函数名相同, 返回参数相同, 参数不同的函数 ( 同名不同参 )
      • image.png
    • 详情:【作业题目篇1-2】中的代码:
  • 内联函数
    • 关键字:inline
    • 作用:
      • 在编译时, 自动将内联函数替换掉函数调用处, 消除函数调用时的系统开销, 提高运行速度(容易理解层面去讲就是不需要系统再去找这个函数, 并传递进去)
        • 使用内联函数前: image.png
        • 使用内联函数后:
        • image.png
  • 默认参数值的函数

    • 即在函数体内的行参自带数值, 调用时, 可以不传参
    • 注意⚠️:
      • 所有取默认值的参数必须在不取默认值参数的右边
        • 即:image.png
      • 设计函数时, 请考虑默认值的排列顺序, 避免出现你需要第二个参数, 但不需要第一个默认参数的情况
    • image.png

      题目

  • image.png

    练习三

    知识点3

  • new / delete

    • 作用: 动态内存管理 (开辟 / 销毁)
    • 基本格式:
      • 指针变量名 = new 类型; // 为指针动态分配存储空间
      • delete 指针名; // 释放指针的存储空间
    • 示例: image.png
    • 为数组分配空间的方式
      • 限定分配空间的个数: int *pc = new int[分配空间个数];
      • 分配空间并进行初始化: int *pc = new char('c');
      • 注意⚠️: 无法同时 既限定空间个数还能初始化的方式
      • 例题:
        • image.png
    • PS注意⚠️:
      • 显式分配( new )的空间, 需要显式释放( delete )该空间; 否则这部分空间将无法被回收
      • 当没有足够的空间分配时, 将返回 NULL, 所以通常要对其进行是否分配成功进行检查
        • image.png
      • 可以为数组动态分配空间
  • 引用 &
    • 详见 作业题目篇1-1
  • 作用域运算符 :: ( 解决变量同名但处于不同范围的问题 )
    • 作用:
        1. 使用某个类中的静态变量 ( 只有静态变量才可以使用 类名::变量名 获取)
        1. 在类外定义类内已经声明了的函数 返回类型 类名::函数名(参数列表){...}
        1. 使用全局变量(即定义在最外面) ::变量名
    • 示例:image.png
    • 运行结果:image.png
  • 强转

    • 一般类型下, c++会自动进行类型转换, 特殊情况下需要进行强制类型转换
    • 方式一: image.png
    • 方式二: image.png

      题目

      image.png
      image.png
      image.png
      image.png

      练习四

      知识点4

      | | public 公有 | protected 保护 | private 私有 | | —- | —- | —- | —- | | 在未声明访问权限时,默认为 | | | ✅ |
  • 友元函数和友元类 -> 详情 作业题目篇 4-1

  • 静态成员:

image.png
image.png
==================================

  • 构造函数不能是虚函数
  • 要实现动态连编,派生类中的虚函数必须完全相同

    多态练习

  • 动态指针

  • 虚函数与普通函数在多态的向上转型面前的使用

    1. #include <iostream>
    2. using namespace std;
    3. class Family
    4. {
    5. public:
    6. virtual void like(){
    7. cout<<"每个家人都喜欢不一样的花"<<endl;
    8. }
    9. void show(){
    10. cout<<"温馨和睦的家庭..."<<endl;
    11. }
    12. };
    13. class Mother : public Family
    14. {
    15. public:
    16. Mother(string f):flower(f){}
    17. void like(){
    18. cout<<"妈妈喜欢"<<this->getFlower()<<endl;
    19. }
    20. void show(){
    21. cout<<"妈妈❤️这个家庭..."<<endl;
    22. }
    23. string getFlower(){
    24. return this->flower;
    25. }
    26. private:
    27. string flower;
    28. };
    29. class Father : public Family
    30. {
    31. public:
    32. Father(string f):flower(f){}
    33. void like(){
    34. cout<<"爸爸喜欢"<<this->getFlower()<<endl;
    35. }
    36. string getFlower(){
    37. return this->flower;
    38. }
    39. void show(){
    40. cout<<"爸爸❤️这个的家庭..."<<endl;
    41. }
    42. private:
    43. string flower;
    44. };
    45. int main()
    46. {
    47. // 分别对三个类创建三个对象
    48. Family b,*ptr;
    49. Mother m("玫瑰");
    50. Father f("菊花");
    51. // 将基类指针指向基类Family
    52. ptr = &b;
    53. ptr->like(); // 指针调用虚函数时(下面的雷同)
    54. ptr->show(); // 指针调用普通成员函数时(下面的雷同)
    55. // 将派生类妈妈的地址给基类指针
    56. ptr = &m;
    57. ptr->like();
    58. ptr->show();
    59. // 将派生类爸爸的地址给基类指针
    60. ptr = &f;
    61. ptr->like();
    62. ptr->show();
    63. return 0;
    64. }
  • 看到这里, 你认为的输出结果是什么呢?

  • 答案:
    • image.png
  • 解析:
    • 这就是动态指针与多态的问题:
    • 对于普通函数show(), 将派生类的地址给基类指针ptr = &m;, 基类使用时会找到自身的实现方法ptr->show(), 完成输出
    • 而对于虚函数like(), 将派生类的地址给基类指针ptr = &m;, 该指针判断自己当前基类的函数是不是虚函数, 如果是那么自动向下寻找也就是谁给了我这个地址, 我就找这个派生类的函数like()并完成输出
      • 例如本题中, 妈妈将自身派生类的地址给了基类指针 ptr, ptr发现自己的like()函数是virtual的, 那么就去找Mother中的like()并完成输出
  • 看完这些, 那么就看看这个题吧
  • image.png
  • 此刻你应该知道输出什么了吧?
  • 答案:
    • Stock class.
    • Stock class.
    • Stock class.

      实验题3-3

      编写程序,定义抽象基类Shape,由它派生出3个派生类: Circle(圆)、Triangle(三角形)和Square(正方形),用虚函数ShowArea()分别显示各种图形的面积。要求用基类指针数组,使它的每一个元素指向一个派生类对象。

  1. #include<iostream>
  2. using namespace std;
  3. const double PI = 3.1415;
  4. class Shape
  5. {
  6. public:
  7. virtual void ShowArea()=0; // 纯虚函数
  8. };
  9. class Circle:public Shape
  10. {
  11. public:
  12. Circle(double r):radius(r){
  13. }
  14. void ShowArea(){
  15. cout<<"圆形的面积为:"<< PI * radius * radius <<endl;
  16. }
  17. private:
  18. double radius;
  19. };
  20. class Square:public Shape
  21. {
  22. public:
  23. Square(double sw):width(sw){
  24. }
  25. void ShowArea(){
  26. cout<<"方形的面积为:"<< width * width <<endl;
  27. }
  28. private:
  29. double width;
  30. };
  31. class Triangle:public Shape
  32. {
  33. public:
  34. Triangle(double w,double h):width(w),height(h){
  35. }
  36. void ShowArea(){
  37. cout<<"三角形的面积为:"<< 0.5 * width * height<<endl;
  38. }
  39. protected:
  40. double width,height;
  41. };
  42. int main()
  43. {
  44. Shape *ptr; // 创建一个Shape指针
  45. // 创建三个派生类对象
  46. Circle circle(3.0);
  47. Square square(3.0);
  48. Triangle triangle(3.0,3.0);
  49. // 将指针指向圆形
  50. ptr = &circle;
  51. ptr->ShowArea();
  52. // 将指针指向方形
  53. ptr = &square;
  54. ptr->ShowArea();
  55. // 将指针指向三角形
  56. ptr = &triangle;
  57. ptr->ShowArea();
  58. return 0;
  59. }
  • 输出结果image.png

    判断下列代码的错误

    image.png

  • 修改后的代码:

    1. #include<iostream>
    2. using namespace std;
    3. template<typename T>
    4. class Compare{
    5. public:
    6. Compare(T a,T b){
    7. x = a;
    8. y = b;
    9. }
    10. T min(){
    11. return (x < y) ? x : y;
    12. }
    13. private:
    14. T x,y;
    15. };
    16. int main(){
    17. Compare <int> com1(3,7);
    18. cout<<"其中的最小值是:"<<com1.min()<<endl;
    19. return 0;
    20. }
  • 错误点:

image.png