我们在写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”头文件。