QT软件实习笔记3

2024.1.15

​​​​​​​

目录

上午:

1. 定义函数指针变量,进而调用函数;

2. 函数指针指向成员函数和静态函数;

1、 C++中,在类或结构中,成员函数与静态函数有何区别?成员字段和静态字段有何区别?

2、 为什么要抽象函数类型?解决同类函数有多个的情况;

3. 课堂练习1;

4. Lambda表达式的语法 1 ;

5. 课堂练习2;

1. 有如右函数:void apply(int *array, int nn, int (*func)(int));将每个元素扩大 2 倍、和 平方 的功能,用Lambda技术实现;

2. 基于一维整型数组的 << 运算符重载;

6. 课堂练习3;

7. C++中的引用概念

1、 在C++语言,有些概念是C++语言所特有的;

2、 何为引用?

3、 引用的用途?

4、 引用和指针的比较?

5、 在C语言和C++中,有一个典型的例子:两数交换;

6、 三类函数;同一范围(同一个文档或同一个类);

8. 自定义头文件;

1、 C++中的头文件有两类

2、 自定义头文件包含什么东西?

3、 自定义头文件示例

9. Lambda表达式的语法 2 ;

1、 常规的匿名函数;无参和带参的;

2、 捕获列表能够捕获什么东西?何为捕获?就是使用;

10.课堂练习4;


上午:

1. 定义函数指针变量,进而调用函数;

void test() {
    int (*pf1)(int) = two;
    auto rr = pf1(11);
    cout << "rr -> " << (rr) << endl;
    int (*pf2)(int) =square;
    rr = pf2(11);
    cout << "rr -> " << (rr) << endl;
}

2. 函数指针指向成员函数和静态函数;

这里所说的成员函数,是指这些函数与类或结构有隶属关系;是与全局函数比较而言的;

1、 C++中,在类或结构中,成员函数与静态函数有何区别?成员字段和静态字段有何区别?

i. 从生活常识中解释成员和静态的概念

       成员数据属于个体;静态数据属于全体;

ii. 举例:

  一个Student类或结构,学号,姓名,年龄,籍贯、专业、入学分数等,这些字段或分量都是属于个人的,即是成员数据;像学生类中的教室、教员、班级编号;这些字段或函数都是属于整体的,属于所有学生的;

iii. 对于成员数据(字段和函数),需要类对象操作;

     用类访问静态成员(字段和函数);

2、 为什么要抽象函数类型?解决同类函数有多个的情况;

struct Aa {
    int add(int a, int b) {
        return a + b;
    }
    void hello() {
        printf("******  hello,gcc! ******\n");
    }
    static void print(string str) {
        cout << "=> " << str << endl;
    }
};
void test() {
    Aa aa;
    Aa *pa = new Aa;
    //::称为作用域运算符;
    int (Aa::*padd)(int, int) =&Aa::add;
    auto rr1 = (aa.*padd)(11, 25);
    cout << "rr1 -> " << (rr1) << endl;
    auto rr2 = (pa->*padd)(1, 2);
    cout << "rr2 -> " << (rr2) << endl;
    void (*pf)(string) =&Aa::print;
    pf("hello,cpp!");
    pf("中国人来啦!");
}

3. 课堂练习1;

创建一个指向结构Aa成员函数hello的指针,来调用它;

struct  Aa{
    int add(int a, int b) {
       return a + b;
    }
    void hello() {
        printf("******,he110,gCC!*******\n”);
    }
    static void print(string str){
        cout << "=> " << str << endl;
    }
};

4. Lambda表达式的语法 1 ;

[capture list] (parameters)mutable throw() -> return-type { statement } 

[capture list]     [捕获列表]

(parameters)     [参数列表]

mutable throw()     [可变规则] 【异常说明】

-> return-type      [返回类型]

{ statement }       [函数体]

1、 Lambda表达式是什么?

它实际上一个匿名函数(来自于C++11版本)

2、 能干什么?

当一个函数只用一次时,就可使用匿名函数;

3、 当我们学习一个新知识点时,有时根据需要,要解决新的问题时,旧的知识点解决不了;相比旧知识解决同样的问题,代码量少,效率高;5+5+5+5+5+5    5*6

4、 对于Lambda表达式,它属于后者;

5、 四种常规函数的Lambda表示法;

i. 无参、无返回;

ii. 无参、有返回;

iii. 有参、无返回;

iv. 有参、有返回;

6、 Lambda表达式之HelloWorld;

void test() {
    int b = 10;  //局部变量
    //创建一个匿名函数实现三数和的功能
    /*auto add = [](int i, float f, double d) {
        cout << "*** 三数之和 ***" << endl;
        return i + f + d;
    };
    auto rr1 = add(10, 3.45f, 3.1415);
    cout << "rr1 -> " << (rr1) << endl;*/
    /*auto rr = [](int i, float f, double d) {
        cout << "*** 三数之和 ***" << endl;
        return i + f + d;
    }(10, 3.45f, 3.1415);
    cout << "rr -> " << (rr) << endl;*/
    cout << "rr -> " << [](int i, float f, double d) {
        cout << "*** 三数之和 ***" << endl;
        return i + f + d;
    }(10, 3.45f, 3.1415) << endl;
}

第三个版本的Lambda表达式,是将函数的:声明、定义、调用三者于一体; 

7. 没有参数的Lambda表达式;当一个匿名函数没有参数时,小括号可以省略;

  void hello();

      int get();
void test() {
    auto af = []() {
        cout << "*** hello! ***" << endl;
    };
    af();
    auto bf = [] {
        return 120;
    };
    cout << "  bf() -> " << [] {
        return 120;
    }() << endl;
    af();
}

5. 课堂练习2;

1. 有如右函数:void apply(int *array, int nn, int (*func)(int));将每个元素扩大 2 倍、和 平方 的功能,用Lambda技术实现;

38dc69dd781643abb8abcd25a92ad5cc.png

void apply(int *array, int nn, int (*func)(int));
void showIntegerArray(int *aa, int nn);
void test() {
    int aa[]{11, 2, 3, 100, 55,};
    int nn = sizeof aa / sizeof *aa;
    showIntegerArray(aa, nn);
    printf("\n");
    //如何将扩大2倍的功能用Lambda表达式实现
    apply(aa, nn, [](int elem) {
        return elem * 2;
    });
    showIntegerArray(aa, nn);
    //如何将元素平方的功能用Lambda表达式实现
    apply(aa, nn, [](int elem) {
        return elem * elem;
    });
    showIntegerArray(aa, nn);
}
void showIntegerArray(int *aa, int nn) {
    if (!aa || nn < 1)
        return;
    for (int i = 0; i < nn; ++i) {
        cout << setw(10) << aa[i];
    }
    printf("\n");
}
void apply(int *array, int nn, int (*func)(int)) {
    if (!array || nn < 1) {
        return;
    }
    for (int i = 0; i < nn; ++i) {
        array[i] = func(array[i]);
    }
}

2. 基于一维整型数组的 << 运算符重载;

#include <iostream>
#include <cstring>  //表示C语言中的string.h
#include <string>  //C++中的string类
#include <iomanip>
using namespace std;
//基于整型一维数组的 << 运算符重载
template<int N>
ostream &operator<<(ostream &out, const int (&raa)[N]) {
    if (!raa || N < 1) {
        return out;
    }
    for (int i = 0; i < N; ++i) {
        out << setw(5) << raa[i];
    }
    out << endl;
    return out;
}
void test();
int main(int argc, char *argv[]) {
    test();  
    return 0;
}
struct Aa {
    int id;
    char name[40];
    friend ostream &operator<<(ostream &out, const Aa &obj) {
        return out << "{" << obj.id << "," << obj.name << "}";
    }
};
void test() {
    double pi = 3.14159; //内置类型
    cout << pi << endl;
    printf("\n");
    Aa aa{1024, "张三 xiao ming"};  //结构对象
    cout << aa << endl;
    printf("\n");
    int array[]{11, 2, 3, 100, 55, 78, 87,};// 数组
    cout << array << endl;
    double dd[]{3.14159, 2.71828, 0.618,};
    cout << dd << endl;
}

6. 课堂练习3;

依照一维整型的输出运算符重载实现代码,将对于一维双精度类型的数组,进行重载;以便于对实型数组用cout << dd << endl; 进行遍历;

//基于实型一维数组的 << 运算符重载

template<int N>
ostream &operator<<(ostream &out, const double (&raa)[N]) {
    if (!raa || N < 1) {
        return out;
    }
    for (int i = 0; i < N; ++i) {
        printf("%10lg", raa[i]);
    }
    printf("\n");
    return out;
}
void test() {
    double pi = 3.14159; //内置类型
    cout << pi << endl;
    printf("\n");
    Aa aa{1024, "张三 xiao ming"};  //结构对象
    cout << aa << endl;
    printf("\n");
    int array[]{11, 2, 3, 100, 55, 78, 87,};// 数组
    cout << array << endl;
    double dd[]{3.14159, 2.71828, 0.618,};
    cout << dd << endl;
}

7. C++中的引用概念

1、 在C++语言,有些概念是C++语言所特有的;

       比如:运算符重载,引用;

2、 何为引用?

        引用就是变量的别名,相当于作家的笔名;作家的本名和别名,都是代表作家本人;最著名的笔名就是鲁迅,鲁迅和周树人两个名字表示一个人;

3、 引用的用途?

        在C++中,引用的重要仅次于指针! 在很多情况下,引用使用更多;用引用代替指针,用法更直观;

4、 引用和指针的比较?

         指针指变量的地址;引用是变量的别名;

5、 在C语言和C++中,有一个典型的例子:两数交换;

i. 在C语言中,通过指针完成两数交换;

ii. 在C++中,既可通过指针,也可以通过引用;

iii. 在C++中,既可通过指针,完成类的多态操作;也可通过引用,完成类的多态操作;

6、 三类函数;同一范围(同一个文档或同一个类);

i. 重载;函数名相同,参数列表不同;只须符合下面一条就是重载;

1. 参数个数不同;

2. 个数相同,类型不同;

3. 个数同,类型同,顺序不同;

void hello();  int hello(); ×

void hello();  int hello(double);  √

int hello(int a,int b); void hello(int a,int b,int c); √

void hello(int a,double d);  double hello(double d,int a); √

void change(int *p1, int *p2) {
    int tt = *p1;
    *p1 = *p2;
    *p2 = tt;
}
void change(int &ref1, int &ref2) {
    int tt = ref1;
    ref1 = ref2;
    ref2 = tt;
}
void change(int *p1, int *p2);
void change(int &ref1, int &ref2);
void test() {
    printf("\n");
    auto a = 145;
    auto b = 3000;
    cout << "a -> " << (a) << endl;
    cout << "b -> " << (b) << endl;
    printf("\n");
    change(&a, &b);
    cout << "a -> " << (a) << endl;
    cout << "b -> " << (b) << endl;
    printf("\n");
    change(a,b);
    cout << "a -> " << (a) << endl;
    cout << "b -> " << (b) << endl;
}
void change(int *p1, int *p2) {
    int tt = *p1;  //tt:145
    *p1 = *p2; //a=3000
    *p2 = tt; //b=145
}
void change(int &ref1, int &ref2) {
    int tt = ref1;
    ref1 = ref2;
    ref2 = tt;
}

ii. 重写;出现在继承链上的多态中,父类和子类;在子类中重写从父类中继承来的函数;在C++中,父类中的那个方法和子类中的继承来的方法,函数原型完全相同; 

struct A {
    virtual void aa() {
        cout << "*** A::aa() ***" << endl;
    }
};
struct B : public A {
    void aa() {
        cout << "*** B::aa() ***" << endl;
    }
};

父类: virtual void aa(); 

子类;void aa();

class Aa {
public:
    virtual void aa() {  //虚函数,标明这个函数可以在子类中重写
        cout << "*** A::aa() ***" << endl;
    }
};
class Bb : public Aa {
public:
    void aa() {
        cout << "*** B::aa() ***" << endl;
    }
};
//用父类型的指针或引用来调用子类中从父类中继承来的方法;
void test() {
    Aa aa;
    Bb bb;
    aa.aa();
    bb.aa();
    printf("\n");
    Aa &ra = bb; //ra就是bb的别名;父类型的引用调用子类的方法;
    ra.aa();
    printf("\n");
    Aa *pa = &bb;
    pa->aa();
    printf("\n");
    Aa *pb = new Bb();
    pb->aa();
    delete pb;
    pb = nullptr;
}

97fc581d5b5548bd9272386ccf7e0982.png

iii. 同类;返回值类型相同,参数列表相同,函数名不同;变量|类型;

8. 自定义头文件;

1、 C++中的头文件有两类

   一是预定义的头文件,如iostream,stdio,time,math等;

   还有一类就是自定义的头文件;

2、 自定义头文件包含什么东西?

i. 预定义头文件;

ii. 通用的辅助性的自定义的函数;

iii. 针对某些数据类型重载的运算符;

3、 自定义头文件示例

gaoming.hpp

#ifndef CPP17_GAOMING_HPP
#define CPP17_GAOMING_HPP
#include <iostream>
#include <cstring> 
#include <string>  
#include <iomanip>
#include <cstdio>
using namespace std;//基于整型一维数组的 << 运算符重载
template<int N>
ostream &operator<<(ostream &out, const int (&raa)[N]) {
    if (!raa || N < 1) {
        return out;
    }
    for (int i = 0; i < N; ++i) {
        out << setw(5) << raa[i];
    }
    printf("\n");
    return out;
}
//基于实型一维数组的 << 运算符重载
template<int N>
ostream &operator<<(ostream &out, const double (&raa)[N]) {
    if (!raa || N < 1) {
        return out;
    }
    for (int i = 0; i < N; ++i) {
        printf("%10lg", raa[i]);
    }
    printf("\n");
    return out;
}
#endif

应用自定义头文件时,只须将其包含到main函数所在源文件中即可;

9. Lambda表达式的语法 2 ;

1、 常规的匿名函数;无参和带参的;

i. 先生成匿名函数;

ii. 调用匿名函数得到结果;

iii. 输出匿名函数的调用结果;

2、 捕获列表能够捕获什么东西?何为捕获?就是使用;

i. 全局变量;

ii. 局部变量;

int gg = 10; //全局变量;
void test() {
    cout << "gg -> " << (gg) << endl;
    int hh = 100; //局部变量
    int ii = 10;
    auto af = [ii, hh] { //只读捕获
        gg++;
        return gg + hh * ii;
    };
auto rr1 = af();
    cout << "rr1 -> " << (rr1) << endl;
    cout << "gg -> " << (gg) << endl;
    printf("\n");
    auto bf = [&ii, &hh] { //可读写捕获
        ii *= 10;
        hh /= 10;
        gg /= 5;
        return gg + hh + ii;
    };
    auto rr2 = bf();
    cout << "rr2 -> " << (rr2) << endl;
    cout << "gg -> " << (gg) << endl;
    cout << "ii -> " << (ii) << endl;
    cout << "hh -> " << (hh) << endl;
    printf("\n");
    //两个局部变量,一可读,一不可改;
    auto cf = [ii, &hh] { //ii只读,hh可读写
        hh++;
        return ii * hh;
    };
    auto rr3 = cf();
    cout << "rr3 -> " << (rr3) << endl;
    printf("\n");
    //如果说所有局部变量都不可改,捕获列表用 = 表示;
    auto df = [=] {
        /*ii++;
        ++hh;*/
        return ii + hh;
    };
    auto rr4 = df();
    cout << "rr4 -> " << (rr4) << endl;
    printf("\n");
    //如果说所有局部变量都可读写,捕获列表用 & 表示;
    auto ef = [&] {
        ii++;
        --hh;
        return ii - hh;
    };
    auto rr5 = ef();
    cout << "rr5 -> " << (rr5) << endl;
    printf("\n");
    /*
     * 如有100个局部变量,99个可改,1个不可改;ii,hh
     */
    auto jj = 3;
    auto ff = [&, jj] {
        ++ii;
        hh--;
        //++jj;
        return ii + hh + jj;
    };
    auto rr6 = ff();
    cout << "rr6 -> " << (rr6) << endl;
    printf("\n");
    auto gf = [=, &jj] {
        jj *= 10;
        /*++ii;
        hh--;*/
        return ii + hh * jj;
    };
    auto rr7 = gf();
    cout << "rr7 -> " << (rr7) << endl;
    printf("\n");
    auto hf = [=](int a, int b) {
        //jj++;
        return a * b + (ii + hh + jj);
    };
    auto rr8 = hf(10, 20);
    cout << "rr8 -> " << (rr8) << endl;
}

10.课堂练习4;

     将两个整数的操作,如int add(int,int); int sub(int,int); int times(int,int); 因为是同类函数,设计用Lambda表达式实现匿名函数,将三个函数放在一个数组,循环调用,得到结果;

1、 同类函数;

2、 抽象出某类函数的数据类型;

3、 三个作为匿名函数出现;

4、 数组操作;

5、 遍历数组,调用每个匿名函数;

第一个版本;

void test() {
    typedef int (*ptrFunction)(int, int);
    auto a = 1450;
    auto b = 1000;
    cout << "a -> " << (a) << endl;
    cout << "b -> " << (b) << endl;
    printf("\n");
    auto af = [](int e1, int e2) {
        return e1 + e2;
    };
    auto bf = [](int e1, int e2) {
        return e1 - e2;
    };
    auto cf = [](int e1, int e2) {
        return e1 * e2;
    };
    auto df = [](int e1, int e2) {
        return e1 / e2;
    };
    ptrFunction functions[]{af, bf, cf, df,};
    //int nn = sizeof functions / sizeof *functions;
    for (int i = 0, nn = sizeof functions / sizeof *functions; i < nn; ++i) {
        auto func = functions[i];
        auto rr = func(a, b);
        cout << "=> " << rr << endl;
    }
}

第二个版本;

void test() {
    typedef int (*ptrFunction)(int, int);
    auto a = 1450;
    auto b = 1000;
    cout << "a -> " << (a) << endl;
    cout << "b -> " << (b) << endl;
    printf("\n");
    ptrFunction functions[]{[](int e1, int e2) {
        return e1 + e2;
    }, [](int e1, int e2) {
        return e1 - e2;
    }, [](int e1, int e2) {
        return e1 * e2;
    }, [](int e1, int e2) {
        return e1 / e2;
    },};
    for (int i = 0, nn = sizeof functions / sizeof *functions; i < nn; ++i) {
        cout << "=> " << functions[i](a, b) << endl;
    }
}

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邶梓鸭~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值