NDK-CPP语言-纯虚函数+函数模版+模版类

时间:2022-04-21 02:09:35

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.tz.ndk.cpp.MainActivity"
android:orientation="vertical">

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1.C++中:父类类型指针一些注意问题"
android:onClick="clickCppSuperClassPointer"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="2.C++中:纯虚函数(抽象类)"
android:onClick="clickCppPureVirtualFunc"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="3.C++中:函数模版(类似于Java泛型)"
android:onClick="clickCppFuncTemplate"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="4.C++中:函数模版机制(原理)"
android:onClick="clickCppFuncTemplatePrinciple"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="5.C++中:模版类"
android:onClick="clickCppClassTemplate"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="6.函数指针作为函数参数传递"
android:onClick="clickCppFuncPointerParam"/>
</LinearLayout>
java代码:


package com.tz.ndk.cpp;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {

static {
System.loadLibrary("native-lib");
}

private NDKCpp ndkCpp;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ndkCpp = new NDKCpp();


}

public void clickCppSuperClassPointer(View v){
ndkCpp.callCppSuperClassPointer();
}

public void clickCppPureVirtualFunc(View v){
ndkCpp.callCppPureVirtualFunc();
}

public void clickCppFuncTemplate(View v){
ndkCpp.callCppFuncTemplate();
}

public void clickCppFuncTemplatePrinciple(View v){
ndkCpp.callCppFuncTemplatePrinciple();
}

public void clickCppClassTemplate(View v){
ndkCpp.callCppClassTemplate();
}

public void clickCppFuncPointerParam(View v){
ndkCpp.callCppFuncPointerParam();
}


// //java中的抽象类
// public abstract class Test {
// public abstract void tet();
// }
//
// public class TestOne extends Test{
//
// @Override
// public void tet() {
//
// }
//
// }

//Java中方法泛型定义
//最小值
// public void getMin(int a,int b){
//
// }
// public void getMin(float a,float b){
//
// }
// public void getMin(double a,double b){
//
// }
//
// public <T> void getMin(T a,T b){
//
// }
//
// //getMin(10.23,20.354);

//在Java中
// class BaseDao<T>{
// private T t;
// public BaseDao(T t){
// this.t = t;
// }
// }
// class UserDao extends BaseDao<Integer>{
// public UserDao(Integer value){
// super(value);
// }
// }

//这个是Java中这样做
class BaseDao<T>{
private T t;
public BaseDao(T t){
this.t = t;
}
}
class UserDao<T> extends BaseDao<T>{
public UserDao(T value){
super(value);
}
}

class AndroidUserDao extends UserDao<Integer>{
public AndroidUserDao(Integer value){
super(value);
}
}


}
public class NDKCpp {    //1.C++中:父类类型指针一些注意问题    public native void callCppSuperClassPointer();    //2.C++中:纯虚函数(抽象类)    public native void callCppPureVirtualFunc();    //3.C++中:函数模版(类似于Java泛型)    public native void callCppFuncTemplate();    //4.C++中:函数模版机制(原理)    public native void callCppFuncTemplatePrinciple();    //5.C++中:模版类    public native void callCppClassTemplate();    //6.函数指针作为函数参数传递    public native void callCppFuncPointerParam();}
c代码:

Company.h

#ifndef DREAM_NDK_CPP_11_11_19_COMPANY_H
#define DREAM_NDK_CPP_11_11_19_COMPANY_H

#import <android/log.h>

//1.C++中:父类类型指针一些注意问题
//1.1 回顾
//class Company{
//public:
// //发工资
// virtual void salary(){
// __android_log_print(ANDROID_LOG_INFO,"main","发工资");
// }
//};
//class AliCompany : public Company{
//public:
// //发工资
// virtual void salary(){
// __android_log_print(ANDROID_LOG_INFO,"main","阿里巴巴发工资");
// }
//};

//1.2 分析对象大小
//class Company{
//private:
// //公司名称
// char* name;
//public:
// //发工资(普通函数)
// virtual void salary(){
// __android_log_print(ANDROID_LOG_INFO,"main","发工资");
// }
//
// //招聘
// virtual void recruitment(){
// __android_log_print(ANDROID_LOG_INFO,"main","招聘");
// }
//
//};

//1.3 分析对象数组存在的一些问题
//class Company{
//public:
// //公司名称
// char* name;
//public:
//
// Company(char* name){
// this->name = name;
// }
//
// //发工资(普通函数)
// virtual void salary(){
// __android_log_print(ANDROID_LOG_INFO,"main","发工资");
// }
//
//};
//class TzCompany : public Company{
//private:
// int age;
//public:
// TzCompany(char* name,int age) : Company(name){
// this->age = age;
// }
// virtual void salary(){
// __android_log_print(ANDROID_LOG_INFO,"main","潭州发工资......");
// }
//};



//2.C++中:纯虚函数(java中的抽象类)
//在Java中
//为什么要使用抽象类?
//总结:本质核心就是为了完善多态
//通俗:约束和标准

//今天在C++中
//2.1 语法定义
//class Company{
//public:
//// //虚函数定义
//// virtual void salary(){
////
//// }
// //申明纯虚函数
// virtual void salary() = 0;
//};
//class TzCompany : public Company{
//public:
// //注意:你不实现语法检测不报错,但是编译报错
// //实现
// void salary(){
// __android_log_print(ANDROID_LOG_INFO,"main","潭州发工资......");
// }
//};

//2.2 C++中有没有类似Java的接口定义?
//其实C++中的接口你可以用纯虚函数模拟(可以将C++类中的方法都申明为纯虚函数,也就类似与java中的接口)
//C++中可以支持多继承
//例如:
//class Company{
//public:
// virtual void salary() = 0;
// virtual void recruitment() = 0;
//};


//5.C++中:模版类(Java里面OrmLite、GreenDao(都是数据库))
//5.1 语法定义
//以下就是模版类的定义: template <class T>
//其实也就类似于Java中的类泛型
//template <class T>
//class BaseDao{
//private:
// T t;
//public:
// BaseDao(T t){
// this->t = t;
// }
//};
//
//class UserDao : public BaseDao<int>{
//public:
// UserDao(int value) : BaseDao<int>(value){
//
// }
//};

//5.2 父类是模版类,子类也是模版类
//template <class T>
//class BaseDao{
//private:
// T t;
//public:
// BaseDao(T t){
// this->t = t;
// }
//};

//申明类型(子类)
//架构师讲解的MVP架构设计(里面都是泛型)
//template <typename T>
//class UserDao : public BaseDao<T>{
//public:
// UserDao(T value) : BaseDao<T>(value){
// //业务处理
// }
//};
//
//class AndroidUserDao : public UserDao<int>{
//public:
// AndroidUserDao(int value) : UserDao<int>(value){
//
// }
//};


//6.函数指针作为函数参数传递



#endif

com_tz_ndk_cpp_NDKCpp.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_tz_ndk_cpp_NDKCpp */

#ifndef _Included_com_tz_ndk_cpp_NDKCpp
#define _Included_com_tz_ndk_cpp_NDKCpp
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_tz_ndk_cpp_NDKCpp
* Method: callCppSuperClassPointer
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppSuperClassPointer
(JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppPureVirtualFunc
(JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFuncTemplate
(JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFuncTemplatePrinciple
(JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppClassTemplate
(JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFuncPointerParam
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

com_tz_ndk_cpp_NDKCpp.cpp
#include <iostream>
#include "com_tz_ndk_cpp_NDKCpp.h"

using namespace std;

//1.C++中:父类类型指针一些注意问题
#import "Company.h"
//1.1 回顾
//void salary(Company &company){
// company.salary();
//}
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppSuperClassPointer
(JNIEnv *, jobject){
//1.1 回顾
// AliCompany aliCompany;
// //需要申明为虚函数,才会调用子类方法
// //多态
// //虚函数:
// //第一点:在类继承体系中存在
// //第二点:同时覆盖父类的方法
// //第三点:同时父类引用指向子类实例
// salary(aliCompany);


//1.2 分析对象的大小
// Company company;
//测试结果一:发现我们将方法申明为虚函数,对象的大小增大了,对象大小8
//测试结果二:我们在类中添加了两个虚函数包括一个属性,结果对象的大小是8
//总结分析: 添加了virtual关键字修饰函数,那么对象会多一个指针,这个指针指向一个虚函数表
//虚函数表:包括了当前类中的所有的虚函数
// __android_log_print(ANDROID_LOG_INFO,"main","company大小: %d", sizeof(company));


//1.3 分析对象数组存在的一些问题
// TzCompany tzCompany[] = {TzCompany("潭州教育",9),TzCompany("潭州软件",4),TzCompany("潭州语言",4)};
//// //回顾:数组保存是首地址
//// //子类
//// TzCompany* tz_com_p = tzCompany;
//// //通过指针位移方式遍历指针
//// tz_com_p++;
//// __android_log_print(ANDROID_LOG_INFO,"main","公司名称: %s",tz_com_p->name);
//
// //父类引用指向子类实例
// //效果演示:发现是乱码
// //分析问题:因为指针++核心本质=首地址+对象实际大小
// //company大小是8
// //tzCompany大小是12
// //例如:
// //tzCompany = 假设首地址=0x0000002
// //tzCompany++ = 首地址++ = 0x0000014
// //company = 假设首地址=0x0000002
// //company++ = 首地址++ = 0x0000010
// //总结:如果一样大就能够找到,不一样就报错或者说乱码
//解决方案:循环遍历
// Company* com_p = tzCompany;
// com_p++;
// __android_log_print(ANDROID_LOG_INFO,"main","公司名称: %s",com_p->name);

}



//2.C++中:纯虚函数(抽象类)
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppPureVirtualFunc
(JNIEnv *, jobject){
// TzCompany company;
// company.salary();
}



//3.C++中:函数模版(类似于Java泛型)
//3.1 普通的写法
//int getMin(int a,int b){
// return a < b ? a : b;
//}
//char getMin(char a,char b){
// return a < b ? a : b;
//}
//double getMin(double a,double b){
// return a < b ? a : b;
//}

//3.2 函数模版
//定义函数模版类型(申明一个函数模版)
//template <typename T>
//T getMin(T a,T b){
// return a < b ? a : b;
//}

//3.3 函数模版和函数重载同时存在
//int getMin(int a,int b){
// __android_log_print(ANDROID_LOG_INFO,"main","调用了函数重载");
// return a < b ? a : b;
//}
//template <typename T>
//T getMin(T a,T b){
// __android_log_print(ANDROID_LOG_INFO,"main","调用了模版函数");
// return a < b ? a : b;
//}

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFuncTemplate
(JNIEnv *, jobject){
//3.1 普通的写法
// getMin(10,20);
// getMin('A','B');
// getMin(10.545,20.343);

//3.2 函数模版
// int result = getMin(10,20);
// char result = getMin('A','B');
// float a = 10.5;
// float b = 20.6;
// float result = getMin(a,b);
// __android_log_print(ANDROID_LOG_INFO,"main","值:%lf",result);

//3.3 函数模版和函数重载同时存在
//调用了函数重载
// int a = 100;
// int b = 200;
// int result = getMin(a ,b);

//调用了模版方法
// char a = 'a';
// char b = 'b';
// char result = getMin(a ,b);
//总结:优先匹配普通方法,如果匹配不到,再去匹配函数模版
}



//4.C++中:函数模版机制(原理)
//编译过程(4个步骤)
//第一步:预处理文件(后缀名.i文件)
//第二步:转成汇编文件(后缀名.s文件)
//第三步:转成目标文件(后缀名.o文件)
//第四步:链接生成目标文件(可执行文件)
//template <typename T>
//T getMin(T a,T b){
// __android_log_print(ANDROID_LOG_INFO,"main","调用了模版函数");
// return a < b ? a : b;
//}
//
////添加方法是有编译器自动完成
//int getMin(int a,int b){
// return a < b ? a : b;
//}
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFuncTemplatePrinciple
(JNIEnv *, jobject){
// int result = getMin(10,30);
// getMin(10,30);
}


//5.C++中:模版类
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppClassTemplate
(JNIEnv *, jobject){

}


//6.函数指针作为函数参数传递
//int getMin(int a,int b){
// return a < b ? a : b;
//}
//6.1 函数指针(别名方式实现)
//typedef int(*get_min_p)(int a,int b);
////这个将函数指针的别名作为参数
//void biz(get_min_p p,int a,int b){
// int result = p(a,b);
// __android_log_print(ANDROID_LOG_INFO,"main","值:%d",result);
//}

//6.2 直接使用
//这个将函数指针直接作为参数
//void biz2(int(*p)(int a,int b),int a,int b){
// int result = p(a,b);
// __android_log_print(ANDROID_LOG_INFO,"main","值:%d",result);
//}

//6.3 补充内容:函数指针结合函数模版(行不通)
//template <typename T>
//void getMin(int a,int b){
// //return a < b ? a : b;
//}
//typedef void(*get_min_p)(T a,T b);
//void biz(get_min_p p,int a,int b){
//
//}

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFuncPointerParam
(JNIEnv *, jobject){
//6.1 函数指针(别名方式实现)
// get_min_p p = getMin;
// int result = p(10,20);
// __android_log_print(ANDROID_LOG_INFO,"main","值:%d",result);

//6.2 直接使用
// biz(getMin,10,20);
// biz2(getMin,10,20);

//6.3 补充内容
}




整理自示例代码