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;
    }
};
  • 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;
}

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

动态多态–函数重写
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;
}
  • 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;
}
  • 方法前面加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) {
        // 查询操作,省略代码...
    }
};
  • 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,恭喜你进入
6.c++模板函数
template <typename TT>
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<string>("AAA", "BBB");

    return 0;
}

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析构函数
  • 构造函数是先执行父类,然后执行子类
  • 析构函数是先执行子类,然后执行父类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值