• Android NDK篇-C++虚函数、纯虚函数、完全纯虚函数与模板函数


    1.c++对象成员变量初始化

    // 课程类
    class Course {
    private:
        string name;
    public:
        Course(string name) :name(name) {}
    
        string  getName(){
            return this->name;
        }
    };
    
    class Student  {
    private:
        Course course; // 对象成员
    public:
        Student(Course course1, string courseNameInfo)
    
    //           :course(course1) 
                 :course(courseNameInfo) // 第三种方式, 对象(string内容)  直接初始化Course构造函数
    
        {
    //         this->course = course1; // 第一种方式(对象=对象) 编译阶段不认可
        }
    
        Course getCourse(){
            return this->course;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • c++ 类Student 里边包含了Course 类型成员变量,一般会想到this->course = course1; 但是对象成员是不允许的,编译不通过。(无法确认是否真的给course对象成员初始化了)
    • 可以采用course(course1)这个方式:编译阶段认可的 对象=对象 对象直接的赋值而已
    • 也可以采用course(courseNameInfo)这个方式:直接初始化Course的构造函数进行初始化

    2.c++多态(虚函数)

    多态:父类的引用指向子类的对象,同一个方法有不同的实现,重写(动态多态)和 重载(静态多态)

    静态多态–函数重载

    void add(int number1, int number2) {
        cout << number1 + number2 << endl;
    }
    
    void add(float number1, float number2) {
        cout << number1 + number2 << endl;
    }
    
    void add(double number1, double number2) {
        cout << number1 + number2 << endl;
    }
    
    int main() {
        add(10000, 10000);
        add(1.9f, 2.8f);
        add(545.4, 654.54);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    静态多态 (编译期已经决定,调用哪个函数了,这个就属于静态多态的范畴) 重载(静态多态)

    动态多态–函数重写

    class BaseActivity {
    public:
        virtual void onStart() {
            cout << "BaseActivity onStart" << endl;
        }
    };
    
    class HomeActivity : public BaseActivity {
    public:
        void onStart() { // 重写父类的函数
            cout << "HomeActivity onStart" << endl;
        }
    };
    
    class LoginActivity : public BaseActivity {
    public:
        void onStart() { // 重写父类的函数
            cout << "LoginActivity onStart" << endl;
        }
    };
    
    // 在此函数 体系多态,例如:你传入HomeActivity,我就帮你运行HomeActivity
    void startToActivity(BaseActivity * baseActivity) {
        baseActivity->onStart();
    }
    
    int main() {
    
        BaseActivity * activity1 = new HomeActivity();
        BaseActivity * activity2 = new LoginActivity();
        startToActivity(activity1);
        startToActivity(activity2);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • Java语言默认支持多态
    • C++默认关闭多态,需要开启多态,在父类上给函数增加 virtual关键字 ,编程虚函数(加上虚的意思是在程序运行的时候才确认类型)

    3.C++纯虚函数

    class BaseActivity {
    private:
        void setContentView(string layoutResID) {
            cout << "XmlResourceParser解析布局文件信息... 反射" << endl;
        }
    
    public:
        // 1.普通函数
        void onCreate() {
            setContentView(getLayoutID());
            initView();
            initData();
            initListener();
        }
    
        // 2.抽象函数/纯虚函数
        // virtual string getLayoutID(); // 虚函数
        virtual string getLayoutID() = 0; // 纯虚函数
        virtual void initView() = 0;
        virtual void initData() = 0;
        virtual void initListener() = 0;
    };
    
    // 子类 MainActivity 如果没有重新父类的纯虚函数,自己就相当于 抽象类了
    class MainActivity : public BaseActivity {  
    
        string getLayoutID() {
            return "R.layout.activity_main";
        }
    
        void initView()  {
            // Button btLogin = findViewById(R.id.bt_login);
        }
    
        void initData() {
            // tvInfo.setText("info...");
        }
    
        void initListener() {
            /*btLogin.setOnClickListener(new View.OnClickListener() {
                       @Override
                       public void onClick(View v) {
    
                       }
                   });*/
    
        }
    };
    
    int main() {
    
        // 错误:抽象类型 MainActivity 绝对不能实例化
        // MainActivity mainActivity;
    
        // 重新了父类所有的纯虚函数
        MainActivity mainActivity;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 方法前面加virtual 并让函数=0,这样就是纯虚函数了
    • 包含纯虚函数的c++类,相当于java的抽象类,继承抽象类的类必须实现父类的虚函数,否则自身便自动变为抽象类了
    • 纯虚函数相当于java的抽象方法

    4.c++全纯虚函数

    class Student {
        int _id;
        string name;
        int age;
    };
    
    // 此类所有的函数都是纯虚函数,就相当于 Java的接口
    class ISudent_DB {
        virtual void insertStudent(Student student) = 0;
        virtual void deleteStudent(int _id) = 0;
        virtual void updateStudent(int _id, Student student) = 0;
        virtual Student queryByStudent(Student student) = 0;
    };
    
    class Student_DBImpl1 : public ISudent_DB {
    public:
        void insertStudent(Student student) {
            // 插入操作,省略代码...
        }
    
        void deleteStudent(int _id) {
            // 删除操作,省略代码...
        }
    
        void updateStudent(int _id, Student student) {
            // 更新操作,省略代码...
        }
    
        Student queryByStudent(Student student) {
            // 查询操作,省略代码...
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • c++一个类全是纯虚函数,就相当于java的接口,由于允许多继承,也有了实现接口的可能。

    • c++本身没有接口

    5.c++全纯虚函数应用(函数回调)

    // 数据Bean
    class SuccessBean {
    public:
        string username;
        string userpwd;
    
        SuccessBean(string username, string userpwd)
                :username(username), userpwd(userpwd) {}
    };
    
    // 登录响应的接口  成功,错误
    class ILoginResponse {
    public:
        // 登录成功
        virtual void loginSuccess(int code, string message, SuccessBean successBean) = 0;
    
        // 登录失败
        virtual void loginError(int code, string message) = 0;
    };
    
    // 登录的API动作
    void loginAction(string name, string pwd, ILoginResponse & loginResponse) {
        if (name.empty() || pwd.empty()) {
            cout << "用户名或密码为空!" << endl;
            return;
        }
    
        if ("lpf" == name && "123" == pwd) {
            loginResponse.loginSuccess(200, "登录成功", SuccessBean(name, "恭喜你进入"));
        } else {
            loginResponse.loginError(404, "登录错误,用户名或密码错误...");
        }
    }
    
    // 接口实现类
    class ILoginResponseImpl : public ILoginResponse {
    public:
        // 登录成功
        void loginSuccess(int code, string message, SuccessBean successBean) {
            cout << "恭喜登录成功 " << "code:" << code << " message:" << message
                 << "successBean:" << successBean.username << "," << successBean.userpwd << endl;
        }
    
        // 登录失败
        void loginError(int code, string message) {
            cout << " 登录失败 " << "code:" << code << " message:" << message << endl;
        }
    };
    
    int main() {
        
        string username;
        cout << "请输入用户名.." << endl;
        cin >> username;
    
        string userpwd;
        cout << "请输入密码.." << endl;
        cin >> userpwd;
    
        ILoginResponseImpl iLoginResponse;
        loginAction(username, userpwd, iLoginResponse);
    
        return 0;
    }
    
    日志输出:
    请输入用户名..
    lpf
    请输入密码..
    123
    恭喜登录成功 code:200 message:登录成功successBean:lpf,恭喜你进入
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    6.c++模板函数

    template 
    void addAction(TT n1, TT n2) {
        cout << "模板函数:" << n1 + n2 << endl;
    }
    
    int main() {
        addAction(1, 2);
        addAction(10.2f, 20.3f);
        addAction(545.34, 324.3);
        addAction("AAA", "BBB");
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    c++使用template关键字就可以申明一个模板,然后通过typename 来执行名称 名称可以随便写,在java相当于泛型

    7.存在函数继承的情况下,析构函数执行的顺序

    class Person {
    public:
        string name;
    
        Person(string name) : name(name) {cout << "Person构造函数" << endl;}
    
        ~Person()  {cout << "Person析构函数" << endl;}
    
        virtual void test() {
            cout << "父 test..." << endl;
        }
    };
    
    class Student : public Person {
    public:
        string name;
    
        Student(string name) : Person(name) {
            cout << "Student构造函数" << endl;
        }
    
        ~Student()  {cout << "Student析构函数" << endl;}
    
        void test() {  //如果子类重写了  不管父类虚不虚 都执行子类
            cout << "子 test..." << endl;
        }
    };
    
    int main() {
    
        Student student1("A");
        student1.test();
    
        return 0;
    }
    
    日志输出:
    Person构造函数
    Student构造函数
    子 test...
    Student析构函数
    Person析构函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 构造函数是先执行父类,然后执行子类
    • 析构函数是先执行子类,然后执行父类
  • 相关阅读:
    原来,BI数据分析也是有模板的
    CentOS 7 手动安装OpenStack
    Docker入门
    DenseNet 浅析
    Java学习笔记(二十四)
    Excel直接打开csv文件后,数据不能正常显示的解决方法
    彻底了解什么是POE交换机!!!
    新一代垃圾回收器—ZGC
    TV-SAM 新型零样本医学图像分割算法:GPT-4语言处理 + GLIP视觉理解 + SAM分割技术
    低代码开发平台NocoBase的安装
  • 原文地址:https://blog.csdn.net/u014078003/article/details/126267947