NDK-CPP语言-构造函数+New和Delete和Static关键字+对象大小

46 篇文章 1 订阅
42 篇文章 0 订阅
public class NDKCpp {

    //1.C++中构造函数
    public native void callCppConstruct();

    //2.C++中new关键字、delete关键字
    public native void callCppNewOrDelete();

    //3.C++中static关键字
    public native void callCppStatic();

    //4.C++中对象的大小
    public native void callCppObjectSize();

    //5.C++中const修饰函数(常量属性、常量函数)
    public native void callCppConstFunc();

    //6.C++中友元函数
    public native void callCppFriendFunc();

    //7.C++中友元类
    public native void callCppFriendClass();

}

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:    callCppConstruct
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppConstruct
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppNewOrDelete
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppStatic
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppObjectSize
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppConstFunc
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFriendFunc
        (JNIEnv *, jobject);

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFriendClass
        (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

com_tz_ndk_cpp_NDKCpp.cpp

#include <iostream>
#include "com_tz_ndk_cpp_NDKCpp.h"
#include "bean/Student.h"
#include "bean/StaticClass.h"

using namespace std;


//1.C++中构造函数
//问题一:
//需求:Teacher类中没有提供无参数构造函数,在Student类中定义一个Teacher属性变量?
//发现问题:会报错(没有初始化)
//解决方案:初始化

//问题二:什么时候析构函数调用?
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppConstruct
    (JNIEnv *env, jobject jobj){
    //创建
    //首先创建两个Teacher对象
    //接下来创建一个Student对象
    //Student student = Student("陈国军","Grace","Dream");

    //释放
    //首先析构Student
    //写下来析构Teacher

    //注意:顺序类似于(栈数据结构: 先进后出,后进先出)
    //这个也是C++中对对象内存进行的管理机制(管理规则)
}


//2.C++中new关键字、delete关键字
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppNewOrDelete
        (JNIEnv *, jobject){
    //2.1 基本数据类型
    //C语言中
    //在我们堆内存开辟一块内存为int空间
//    int *p = (int*)malloc(sizeof(int));
//    *p = 100;
//    //释放内存
//    free(p);
//    p = NULL;

//    char *cp = (char*)malloc(sizeof(char));
//    *cp = 'a';
//    //释放内存
//    free(cp);
//    cp = NULL;

    //C++中提供非常简便方式(采用new、delete关键字)
    //new int相当于(int*)malloc(sizeof(int))
//    int *p = new int;
//    *p = 100;
//    //释放内存
    delete p;
    free(p);

    //2.2 数组类型
    //在C语言中(动态内存分配)
    //返回的p就是数组的首地址,通过指针位移方式一个个读取
//    int *p = (int*)malloc(sizeof(int)*10);
//    p[0] = 100;
//    free(p);

    //C++中
//    int *p = new int[10];
//    p[0] = 100;
//    //注意:释放数组
//    delete[] p;


    //2.3 分配对象
    //一下写法是允许的,C++中支持C的混合编程
//    Teacher* teacher = (Teacher*)malloc(sizeof(Teacher));
//    teacher->setName("Dream");
//    //释放内存
//    free(teacher);

    //直接C++中语法
    //这个开辟内存栈内存(自动管理)
//    Teacher teacher1 = Teacher();
    //开辟的是堆内存
//    Teacher* teacher = new Teacher();
//    teacher->setName("Dream");
//    delete teacher;

}


//3.C++中static关键字
//3.1 static修饰属性
//3.2 static修饰函数

//可以这样写
//注意:需要在函数的外部进行初始化
int StaticClass::sex = 100;

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppStatic
        (JNIEnv *env, jobject jobj){
//    StaticClass staticClass = StaticClass("Dream");
//    staticClass.sex = 100;
//    __android_log_print(ANDROID_LOG_INFO,"main","sex值: %d",StaticClass::sex);

    //访问静态方法(必须指定类名)
    StaticClass::toString();

}


//4.C++中对象的大小
//回想:结构体大小
//根据结果:ObjectSizeA、ObjectSizeB、ObjectSizeC大小分别是8、12、12

//内存分配
//C++中类对象的属性和成员函数内存分开存储的
//普通属性:存储在对象中,与结构体存储规则一样
//静态属性:存在在静态数据区中,(内存区:栈、堆、静态区、全局区、代码区)
//成员函数:存储在代码区


//问题:既然成员函数都是放置在代码区,共享,那么函数怎么知道当前访问的是哪一个对象?
//解决方案:this区分
#include "bean/ObjectSize.h"
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppObjectSize
        (JNIEnv *env, jobject jobj){
    __android_log_print(ANDROID_LOG_INFO,"main","ObjectSizeA大小: %d", sizeof(ObjectSizeA));
    __android_log_print(ANDROID_LOG_INFO,"main","ObjectSizeB大小: %d", sizeof(ObjectSizeB));
    __android_log_print(ANDROID_LOG_INFO,"main","ObjectSizeC大小: %d", sizeof(ObjectSizeC));

    //C++中类的底层实现相当于就是一个结构体

    ObjectSizeC c1;
    ObjectSizeC c2;
    ObjectSizeC c3;

    c1.toString();
    c2.toString();
    c3.toString();

}


//5.C++中const修饰函数(常量属性、常量函数)
//const修饰什么?
//属性不能够修改
//总结:const修饰的this指针所指向的内存区域不能够修改
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppConstFunc
        (JNIEnv *env, jobject jobj){
    __android_log_print(ANDROID_LOG_INFO,"main","C++中const修饰函数(常量属性、常量函数)");
}


//6.C++中友元函数
//需求:我要访问私有属性
#include "bean/FriendFunc.h"

//友元函数实现
void update_name(FriendFunc *func,char *name){
    func->name = name;
}

JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFriendFunc
        (JNIEnv *, jobject){
    FriendFunc* friendFunc = new FriendFunc();
    update_name(friendFunc,"Hello");
    __android_log_print(ANDROID_LOG_INFO,"main","值: %s",friendFunc->getName());
    //硬是要访问?
    //解决方案:友元函数
}


//7.C++中友元类
//需求:A类访问B类中的私有属性或者函数?
//解决方案:友元类(说白了就是Java反射机制的底层实现)
//注意:A类需要申明B类是我的友元类,之后B类就能够访问A类中的任何属性和方法
#include "bean/FriendClass.h"
JNIEXPORT void JNICALL Java_com_tz_ndk_cpp_NDKCpp_callCppFriendClass
        (JNIEnv *env, jobject jobj){
    //打印结果:
    //FriendClassA:创建了2次,拷贝了1次,析构了3次
    //FriendClassB:创建了1次,析构了1次

    //分析:为什么不能够修改?
    //第一次创建:FriendClassA构造函数
//    FriendClassA friendClassA = FriendClassA();
//    friendClassA.setName("Dream");
//
//    __android_log_print(ANDROID_LOG_INFO,"main","修改之前:%s",friendClassA.getName());
//
//    //第二次创建:就是因为FriendClassB有一个FriendClassA属性调用构造函数(因为对象属性需要初始化)
//    FriendClassB friendClassB;
//    //拷贝对象:实参初始化行参,这个时候也会进行场景对象拷贝
//    //第一次析构(第一次析构是行参):因为行参在update_friendClassA方法中使用完毕,那么立马析构行参对象
//    friendClassB.update_friendClassA(friendClassA,"Jack");
//
//    __android_log_print(ANDROID_LOG_INFO,"main","修改之后:%s",friendClassA.getName());

    //纠正
    //第二次析构:析构friendClassA
    //第三次析构:析构friendClassB中的friendClassA属性

    //怎么才能够实现修改?
    //解决方案
    //解决方案一:传递指针
//    FriendClassA* friendClassA = new FriendClassA();
//    friendClassA->setName("Dream");
//
//    __android_log_print(ANDROID_LOG_INFO,"main","修改之前:%s",friendClassA->getName());
//
//    FriendClassB friendClassB;
//    friendClassB.update(friendClassA,"Jack");
//    __android_log_print(ANDROID_LOG_INFO,"main","修改之后:%s",friendClassA->getName());


    //解决方案二:传递指针的引用
    FriendClassA friendClassA = FriendClassA();
    friendClassA.setName("Dream");

    __android_log_print(ANDROID_LOG_INFO,"main","修改之前:%s",friendClassA.getName());

    FriendClassB friendClassB;
    friendClassB.update_p(friendClassA,"Jack");
    __android_log_print(ANDROID_LOG_INFO,"main","修改之后:%s",friendClassA.getName());




}


ConstFunc.h

#ifndef DREAM_NDK_CPP_11_5_16_CONSTFUNC_H
#define DREAM_NDK_CPP_11_5_16_CONSTFUNC_H


class ConstFunc {
private:
    int age;
    char* name;
public:
    void toString() const {
        //不允许修改
//        age = 100;
//        name = 100;
//        this = (ConstFunc*)0x1211323;
    }
};


#endif //DREAM_NDK_CPP_11_5_16_CONSTFUNC_H

FriendClass.h

#ifndef DREAM_NDK_CPP_11_5_16_FRIENDCLASS_H
#define DREAM_NDK_CPP_11_5_16_FRIENDCLASS_H


class FriendClassA {
private:
    int age;
    char* name;
    void toString();

    //声明FriendClassB是FriendClassA的朋友
    friend class FriendClassB;

public:
    FriendClassA();

    ~FriendClassA();

    FriendClassA(const FriendClassA &friendClassA);

    void setName(char* name);
    char* getName();

};

class FriendClassB {
private:
    FriendClassA friendClassA;

public:
    FriendClassB();

    ~FriendClassB();

    FriendClassB(const FriendClassB &friendClassB);

    void myprint();

    void update_friendClassA(FriendClassA friendClassA,char* name);

    //传递指针
    void update(FriendClassA* friendClassA,char* name);


    //传递指针的引用
    void update_p(FriendClassA &friendClassA,char* name);

};


#endif //DREAM_NDK_CPP_11_5_16_FRIENDCLASS_H
FriendClass.cpp

#include "FriendClass.h"
#include <android/log.h>



FriendClassA::FriendClassA() {
    __android_log_print(ANDROID_LOG_INFO,"main","FriendClassA构造函数");
}

FriendClassA::~FriendClassA() {
    __android_log_print(ANDROID_LOG_INFO,"main","FriendClassA析构函数");
}

FriendClassA::FriendClassA(const FriendClassA &friendClassA) {
    this->age = friendClassA.age;
    this->name = friendClassA.name;
    __android_log_print(ANDROID_LOG_INFO,"main","FriendClassA拷贝函数");
}

void FriendClassA::toString() {

}


void FriendClassA::setName(char *name) {
    this->name = name;
}

char* FriendClassA::getName() {
    return this->name;
}


/************下面是B类**********/



FriendClassB::FriendClassB() {
    __android_log_print(ANDROID_LOG_INFO,"main","FriendClassB构造函数");
}

FriendClassB::~FriendClassB() {
    __android_log_print(ANDROID_LOG_INFO,"main","FriendClassB析构函数");
}

FriendClassB::FriendClassB(const FriendClassB &friendClassB) {
    __android_log_print(ANDROID_LOG_INFO,"main","FriendClassB拷贝函数");
}

void FriendClassB::update_friendClassA(FriendClassA friendClassA,char* name) {
    friendClassA.name = name;
}

void FriendClassB::update(FriendClassA* friendClassA, char *name) {
    friendClassA->name = name;
}

void FriendClassB::update_p(FriendClassA &friendClassA, char *name) {
    friendClassA.name = name;
}

void FriendClassB::myprint() {
    friendClassA.age;
    friendClassA.toString();
}

FriendFunc.h

#ifndef DREAM_NDK_CPP_11_5_16_FRIENDFUNC_H
#define DREAM_NDK_CPP_11_5_16_FRIENDFUNC_H


class FriendFunc {
private:
    char* name;
public:
    FriendFunc();

    //声明一个友元函数(friend关键字)
    friend void update_name(FriendFunc *func,char *name);

    char* getName();
};


#endif //DREAM_NDK_CPP_11_5_16_FRIENDFUNC_H
FriendFunc.cpp

#include "FriendFunc.h"

FriendFunc::FriendFunc() {
    this->name = "Dream";
}

char* FriendFunc::getName() {
    return this->name;
}

ObjectSize.h

#ifndef DREAM_NDK_CPP_11_5_16_OBJECTSIZE_H
#define DREAM_NDK_CPP_11_5_16_OBJECTSIZE_H



class ObjectSizeA {
private:
    int a;
    int b;
};

class ObjectSizeB {
private:
    int a;
    int b;
    int c;

public:
    static int d;
};

class ObjectSizeC {
private:
    int a;
    int b;
    int c;
public:
    void toString();
};


#endif //DREAM_NDK_CPP_11_5_16_OBJECTSIZE_H
ObjectSize.cpp

#include "ObjectSize.h"
#include <android/log.h>

void ObjectSizeC::toString() {
    __android_log_print(ANDROID_LOG_INFO,"main","调用了");
}


StaticClass.h

#ifndef DREAM_NDK_CPP_11_5_16_STATICCLASS_H
#define DREAM_NDK_CPP_11_5_16_STATICCLASS_H

#include <android/log.h>

class StaticClass {
private:
    char* name;
public:

    static int sex;

    StaticClass(char* name);

    ~StaticClass();

    static void toString(){
        __android_log_print(ANDROID_LOG_INFO,"main","sex:%d",sex);
    }

};



#endif //DREAM_NDK_CPP_11_5_16_STATICCLASS_H
StaticClass.cpp

#include "StaticClass.h"
#include <android/log.h>

StaticClass::StaticClass(char *name) {
    this->name = name;
    __android_log_print(ANDROID_LOG_INFO,"main","构造函数");
}

StaticClass::~StaticClass() {
    __android_log_print(ANDROID_LOG_INFO,"main","析构函数");
}
Student.h

#ifndef DREAM_NDK_CPP_11_5_16_STUDENT_H
#define DREAM_NDK_CPP_11_5_16_STUDENT_H

#include "Teacher.h"
#include <android/log.h>

//解决方案:初始化
//第一种写法
//在Teacher类中提供无参数构造方法

//第二种写法
//class Student {
//private:
//    char* name;
//    //班主任老师
//    Teacher headTeacher = "Dream";
//    //科目老师
//    Teacher subjectTeacher = "Dream";
//public:
//    Student(char* name);
//};

//第三种写法
//class Student {
//private:
//    char* name;
//    //班主任老师
//    Teacher headTeacher = Teacher("Grace");
//    //科目老师
//    Teacher subjectTeacher = Teacher("Dream");
//public:
//    Student(char* name);
//};

//第四种写法
//class Student {
//private:
//    char* name;
//    //班主任老师
//    Teacher headTeacher;
//    //科目老师
//    Teacher subjectTeacher;
//public:
//    Student::Student(char *name):headTeacher("Grace"),subjectTeacher("Dream") {
//        this->name = name;
//    }
//};

//第五种写法
//class Student {
//private:
//    char* name;
//    //班主任老师
//    Teacher headTeacher;
//    //科目老师
//    Teacher subjectTeacher;
//public:
//    Student(char *name,char* headName,char* subjectName)
//            :headTeacher(headName),subjectTeacher(subjectName) {
//        this->name = name;
//        __android_log_print(ANDROID_LOG_INFO,"main","Student构造函数");
//    }
//
//    ~Student(){
//        __android_log_print(ANDROID_LOG_INFO,"main","Student析构函数");
//    }
//
//};


#endif //DREAM_NDK_CPP_11_5_16_STUDENT_H

Teacher.h

#ifndef DREAM_NDK_CPP_11_5_16_TEACHER_H
#define DREAM_NDK_CPP_11_5_16_TEACHER_H

#include <android/log.h>

class Teacher {
private:
    char *name;
public:
    Teacher();
    Teacher(char* name);
    ~Teacher();
    void setName(char* name);
};


#endif //DREAM_NDK_CPP_11_5_16_TEACHER_H
Teacher.cpp

#include "Teacher.h"

Teacher::Teacher() {
    this->name = "Dream";
    __android_log_print(ANDROID_LOG_INFO,"main","Teacher构造函数");
}

Teacher::Teacher(char *name) {
    this->name = name;
    __android_log_print(ANDROID_LOG_INFO,"main","Teacher构造函数");
}

Teacher::~Teacher() {
    __android_log_print(ANDROID_LOG_INFO,"main","Teacher析构函数");
}

void Teacher::setName(char *name) {
    this->name = name;
}

MainActivity.java


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();

        //java中访问私有属性?  直接访问?
        try {
            //属于间接访问
            Class<?> clazz = Class.forName("com.tz.ndk.cpp.MainActivity");
            clazz.getField("ndkCpp");
        } catch (Exception e) {
            e.printStackTrace();
        }
        //反射机制访问私有属性
    }

    public void clickCppConstruct(View v){
        ndkCpp.callCppConstruct();
    }

    public void clickCppNewOrDelete(View v){
        ndkCpp.callCppNewOrDelete();
    }

    public void clickCppStatic(View v){
        ndkCpp.callCppStatic();
    }

    public void clickCppObjectSize(View v){
        ndkCpp.callCppObjectSize();
    }

    public void clickCppConstFunc(View v){
        ndkCpp.callCppConstFunc();
    }

    public void clickCppFriendFunc(View v){
        ndkCpp.callCppFriendFunc();
    }

    public void clickCppFriendClass(View v){
        ndkCpp.callCppFriendClass();
    }


}

配置文件CMakeLists.txt:


# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/com_tz_ndk_cpp_NDKCpp.cpp
             src/main/cpp/bean/Student.cpp
             src/main/cpp/bean/Teacher.cpp
             src/main/cpp/bean/StaticClass.cpp
             src/main/cpp/bean/ObjectSize.cpp
             src/main/cpp/bean/ConstFunc.cpp
             src/main/cpp/bean/FriendFunc.cpp
             src/main/cpp/bean/FriendClass.cpp
             )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )




整理自示例代码









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值