您的位置:首页 > 编程语言 > C语言/C++

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

2016-11-07 15:42 330 查看
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_HObjectSize.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_HStaticClass.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_HTeacher.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} )


整理自示例代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: