JNI基础知识(三)C++的特别之处

我们在写JNI开发时,会经常遇到C和C++混编的情况,那我们如何做好区分呢?那只能我们多注意其实现。

首先来看下C++跟C有哪些不同吧:

1、输出

我们是到在C语言中我们输出一般都是用到printf这个函数,但在C++中则不一样,首先其输出库为“iostream”写法如下:

std::cout << "this is c plus plus" << std::endl;

我们可能对“::”这个很不习惯,这个叫做:运算符重载,当然我们也可简化我们的写法,用的C++中的命名空间

//标准命名空间(包含很多标准的定义)
//standard
using namespace std;
//命名空间类似于Java中包(归类)

cout << "this is c plus plus" << endl;

这样写可能就不叫舒服的多啦。当然我们也可以自定义命名空间:

//自定义命名空间
namespace CUSTOM_A{
	int a = 9;
	struct Teacher{
		char name[20];
		int age;
	};
	struct Student{
		char name[20];
		int age;
	};
	
}

namespace CUSTOM_B{
	int a = 12;
	//命名空间嵌套
	namespace CUSTOM_C{
		int c = 90;		
	}
}

void main(){
	cout << CUSTOM_A::a << endl;
	cout << CUSTOM_B::a << endl;
	cout << CUSTOM_B::CUSTOM_C::c << endl;

	//使用命名空间中的结构体
	using CUSTOM_A::Student;
	Student t;
	t.age = 90;

	system("pause");
}

2、类对象

#define PI 3.14
//圆
class MyCircle{
//属性(共用权限访问修饰符)
private:
	double r;
	double s;
public:
	void setR(double r){
		this->r = r;
	}
	//获取面积
	double getS(){
		return PI * r * r;
	}
};

void main(){
	MyCircle c1;
	c1.setR(4);

	cout << "圆的面积:" << c1.getS() << endl;

	system("pause");
}

我们可以发现跟Java还是很像的,但是还有细微的区别,我们使用的时候要注意,比如声明的时候不用new关键字,new之后再讲。

3、结构体

结构体跟C语言的写法也不太一样,我们来看下:

struct MyTeacher{
public:
	char name[20];
	int age;
public:
	void say(){
		cout << this->age << "岁" << endl;
	}
};
void main(){
	MyTeacher t1;
	t1.age = 10;
	t1.say();
	system("pause");
}

我们可以发现其包含了属性在内,而且使用的时候可以不用struct声明。

4、布尔类型

不同于C语言,C++中加入布尔类型,我们来看一下:

void main(){
	//bool isSingle = true;
	bool isSingle = 17;
	//false -17

	if (isSingle){
		cout << "单身" << endl;
		cout << sizeof(bool) << endl;
	}
	else{
		cout << "有对象" << endl;
	}

	int a = 10, b = 20;
	((a > b) ? a : b) = 30;
	cout << b << endl;

	system("pause");
}

我们在上面代码有一点需要注意,不同于我们平时的Java语法,在C++中三目运算可以作为左值,如上面的代码,其b的值输出为30,发生了改变,切记注意。

5、引用

做为C++中最代表性的概念,其对于C++的地位就同与指针对于C的重要。看下基本写法:

void main(){
	//变量名-门牌号(内存空间0x00001的别名,可不可以有多个名字?)
	int a = 10;
	//b就这个内存空间另外一个别名\
	//& C++中的引用
	int &b = a;	
	cout << b << endl;

	system("pause");
}

我们跟指针做一下对比,发现其写法还是比较简单的:

//指针值交换
void swap_1(int *a, int *b){
	int c = 0;
	c = *a;
	*a = *b;
	*b = c;
}

//引用值交换
void swap_2(int &a, int &b){
	int c = 0;
	c = a;
	a = b;
	b = c;
}

void main(){
	int x = 10;
	int y = 20;
	
	printf("%d,%d\n",x,y);
	//swap_1(&x, &y);
	//a成了x的别名
	swap_2(x,y);
	printf("%d,%d\n", x, y);

	system("pause");
}

我们再看一下作为参数传递对比:

struct Teacher{
	char* name;
	int age;
};

void myprint(Teacher &t){
	cout << t.name << "," << t.age << endl;
	t.age = 21;
}

void myprint2(Teacher *t){
	cout << t->name << "," << t->age << endl;	
	//(*t).name 
}

//引用的主要功能:作为函数的参数或返回值
void main(){
	Teacher t;
	t.name = "Jason";
	t.age = 20;
	myprint(t);

	myprint2(&t);

	system("pause");
}

 当然我们也可以作为指针的引用,这样其实现方式就更加丰富啦:

//指针的引用,代替二级指针
struct Teacher{
	char* name;
	int age;
};

void getTeacher(Teacher **p){
	Teacher *tmp = (Teacher*)malloc(sizeof(Teacher));
	tmp->age = 20;
	*p = tmp;
}

//指针的引用,代替二级指针
//Teacher* &p = (Teacher * *p)
void getTeacher(Teacher* &p){
	p = (Teacher*)malloc(sizeof(Teacher));
	p->age = 20;
}

void main(){
	Teacher *t = NULL;

	getTeacher(&t);

	system("pause");
}

 还有一个经常被面试问到,也经常弄混的一个感念,我们要区别一下:指针常量和常量指针。

我们来具体看下两种写法有什么不一样:

void main(){
	//指针常量,指针的常量,不改变地址的指针,但是可以修改它指向的内容
	int a = 2, b = 3;
	int *const p1 = &a;
	//p1 = &b;  //NO
	*p1 = 4;

	//常量指针,指向常量的指针,内容不能修改
	const int *p2 = &a;
	p2 = &b;
	//*p2 = 9;  //NO
}

补充:const 也有许多可分析的东西,简单分析一下。之后单独抽出来分析

//常引用类似于java中final
void myprintf(const int &a){
	cout << a << endl;	
}

void main(){	
	//const int a;
	//引用必须要有值,不能为空
	//int &a = NULL;

	//常引用
	int a = 10, b = 9;
	const int &c = a;

	//字面量
	const int &d = 70;

	//c = b;
	myprintf(c);
	
	system("pause");
}

再看看一下引用的大小:

struct Teacher{
	char name[20];
	int age;
};

void main(){
	Teacher t;

	Teacher &t1 = t;
	Teacher *p = &t;

	cout << sizeof(t1) << endl;//24
//	cout << sizeof(p) << endl;//4
//	cout << sizeof(Teacher) << endl;//24
	system("pause");
}

总结一下:

1.单纯给变量取别名没有任何意义,作为函数参数传递,能保证参数传递过程中不产生副本

2.引用可以直接操作变量,指针要通过取值(*p),间接操作变量,指针的可读性差

6、函数参数

a、函数默认参数

void myprint(int x, int y = 9, int z = 8){
	cout << x << endl;
}
//重载
void myprint(int x,bool ret){
	cout << x << endl;
}

void main(){
	myprint(20);

	system("pause");
}

分析一下:1、不同于java可以传入默认值的参数,注意的是前面一个是传默认值的,后面的也必须传默认值。

                  2、重载的函数不能有可二性,就是其可传参数不能一样。

b、可变参数

void func(int i,...)
{
	//可变参数指针
	va_list args_p;
	//开始读取可变参数,i是最后一个固定参数
	va_start(args_p,i);
	int a = va_arg(args_p,int);
	char b = va_arg(args_p, char);
	int c = va_arg(args_p, int);
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	//结束
	va_end(args_p);
}


void main(){
	func(9,20,'b',30);

	system("pause");
}


//循环读取
void func(int i,...)
{
	//可变参数指针
	va_list args_p;
	//开始读取可变参数,i是最后一个固定参数
	va_start(args_p,i);
	int value;
	while (1){
		value = va_arg(args_p,int);
		if (value <= 0){
			break;
		}
		cout << value << endl;
	}

	//结束
	va_end(args_p);
}

void main(){
	func(9, 20, 40, 30);

	system("pause");
}

注:读取可变参数要引入“stdarg.h”头文件。



 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值