C++引用和指针和void
int int_b = 124;
int *int_b_ptr = &int_b;
int &int_c = int_b;
*int_b_ptr=126;
cout<<int_b;
int_c=128;
cout<<int_b;
最后分别打印126 128
引用和指针在某种程度上没有区别。
void:代表空类型,也就是无类型,只能用于定义指针变量,如void*,当定义了void *p=xxx时,可以通过sizeof(p)是否为4或者8来判断当前运行模式
nullptr
目的:解决NULL带来的二义性问题
void func(int){
count<<"1";
}
void func(int*){
count<<"2";
}
func(NULL) 最后打印1;
func(nullptr)最后打印2;
NULL定义
#define NULL 0
C++11中的结构体和对象
C中的结构体的定义只包含属性而不能有函数的声明和定义,C++11中的结构体扩展了C中的结构体的概念(可以把C++11的类看成对C的结构体的扩展),既可以有属性,又可以有函数。而对于C++11中的结构体和对象,当被编译器编译之后,其实就跟C中的结构体没有区别了
C++11中其他关键字
auto为C++11中的类型推导关键字
C++98/03中auto关键字用于标识具有自动存储期的局部变量,作用不大。比如auto int a =0,它在C++98/03和int a =0一样的,一般都省略掉了auto 关键字,与之相对的static int a =0;标识a是一个静态类型,存储在堆的全局数据区。
C++11中 auto a =20 和 int a=20一样。但是使用auto 变量必须初始化。
auto pi= new auto(1) //pi是int *型指针
const auto *v =&a,u =6 // v是const int *类型static u 是const int 类型
auto限制:
1、auto不能作为函数参数
void func(auto a = 1) {
__android_log_print(4, "CPP11", "func is called");
}
2、auto不能修饰类或者结构体中的非静态成员变量
struct Mystruct {
//auto var = 1;
//static auto var2 = 2;
//error: auto不能修饰类或者结构体中的非静态成员
const static auto var2 = 2;
};
3、auto不能定义数组
4、auto不能推导出模板参数
decltype关键字
用于在编译时期推导出一个表达式的类型,而不需要初始化,语法格式有点像sizeof,
decltype(a);
a=22; //int
float float_b = 0.2;
decltype(int_tmp * float_b) tmp_b; //float
int add(int a ,int b){
return a+b
}
decltype(add(5,6)) tmp_bb; //int 但是tmp_bb没有被初始化,值不确定
ART下C++11中类、函数以及访问权限
public:可以被任意对象访问
protected:只允许子类以及本类的成员函数访问
private:只允许本类的成员函数访问
继承:
public继承,private继承,protected继承
派生类能且只能访问基类的public和protected成员,默认继承方式是private
基类中继承方式子类中public & public继承=> public
访问权限
组合结果
基类中 & 继承方式子类中
public & public继承=> public
public & protected继承=> protected
public & private继承= > private
protected & public继承=> protected
protected & protected继承=> protected
protected & private继承= >private
private & public继承=>子类无权访问
private & protected继承>子类无权访问究;
private & private继承=>子类无权访问
private & protected继承>子类无权访问究;
private & private继承=>子类无权访问
由以上组合结果可以看出
1、public继承不改变基类成员的访问权限
2、private继承使得基类所有成员在子类中的访问权限变为private
3、protected继承将基类中public成员变为子类的protected成员,其它成员的访问权限不变。
4、基类中的private成员不受继承方式的影响,子类永远无权访问。此外,在使用private继承时,还存在另外一种机制:准许访问。
我们已经知道,在基类以private方式被继承时,其public和protected成员在子类中变为private成员。然而某些情况下,需要在子类中将一个或多个继承的成员恢复其在基类中的访问权限。
友元函数和友元类(理解为朋友关系)
私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进仃。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦。因此,C++就有了友元(friend)的概念。打个比方,这相当于是说:朋友是值得信任的,所以可以对他们公开一些自己的隐私。
//person.h
#include "android/log.h"
class person {
private:
int sex;
int age;
int getsexprivate() {
return this->sex;
}
protected:
int getageprotected() {
return this->age;
}
public:
person(int sex, int age) : sex(sex), age(age) {
__android_log_print(4, "CPP11", "%s", "person(int sex,int age) is called");
}
virtual void test(){
__android_log_print(4, "CPP11", "%s", "preson virtual test is called");
}
int getsex();
int getage();
void setsex(int sex);
void setage(int age);
};
//student.h 默认方式继承
#include "person.h"
#include "android/log.h"
class student : person {
public:
student(int sex, int age, int id) : person(sex, age) {
this->id = id;
__android_log_print(4, "CPP11", "%s", "student(int sex, int age,int id)");
}
virtual void test() {
__android_log_print(4, "CPP11", "%s", "student virtual test is called");
}
int getid();
void setid(int id);
friend int getstuid(student *stu);
friend class teacher;
private:
int id;
};
int getstuid(student *stu);
//person.cpp
#include "person.h"
int person::getsex() {
//return this->sex;
return this->getsexprivate();
//访问private函数唯一途径
}
//int getage();
int person::getage() {
return this->age;
}
void person::setage(int age) {
this->age = age;
}
void person::setsex(int sex) {
this->sex = sex;
}
//void setsex(int sex);
//void setage(int age);
//student.cpp
#include "student.h"
int getstuid(student *stu) {
return stu->id;
}
//int getid();
int student::getid() {
//return this->id;
return getageprotected() + getsex();
}
//void setid(int id);
void student::setid(int id) {
this->id = id;
}
#include "person.h"
person man(0, 24);
__android_log_print(4, "CPP11", "manage:%d", man.getage()); //24
C++11中的模板函数和模板类
模板:泛型编程基础。即以一种独立任何特定类型的方式编写代码,ART中大量运用了模板
模板函数:
template <class T>
T add(T a,T b){
return a+b;
}
template <typename T>
T sub(T a ,T b){
return a-b;
}
int res= add(5,6);
int res1=sub(6,5);
float res_f=add(5.2f,5.3f);
auto res_a=add(5.2f,5.3f);
模板类:
template <class M>
class com{
public:
com(M a ,M b ):a(a),b(b){};
M mul(){
return a*b
}
private:
M a;
Mb;
}
com <int> com_int(6,8);
auto res_int=com_int.mul();
Frida hook So模板类模板函数
function hooktemplate() {
var Compute_int_con_addr = Module.getExportByName("libnative-lib.so", "_ZN7ComputeIiEC2Eii");
var Compute_int_add_addr = Module.getExportByName("libnative-lib.so", "_ZN7ComputeIiE3addEv");
var Compute_short_con_addr = Module.getExportByName("libnative-lib.so", "_ZN7ComputeIsEC2Ess");
var Compute_short_add_addr = Module.getExportByName("libnative-lib.so", "_ZN7ComputeIsE3addEv");
//console.log(Compute_int_con_addr);
Interceptor.attach(Compute_int_con_addr, {
onEnter: function (args) {
this.Compute_ptr = ptr(args[0]);
var a = args[1];
var b = args[2];
console.log("Compute<int> Compute(" + a + "," + b + ");");
args[1] = ptr(777); //参数替换
args[2] = ptr(222);
}, onLeave: function (retval) {
Memory.writeInt(this.Compute_ptr, 20); //替换参数第二种
Memory.writeInt(this.Compute_ptr.add(4), 40);
}
});
Interceptor.attach(Compute_int_add_addr, {
onEnter: function (args) {
var Compute_ptr = ptr(args[0]);
var a = Memory.readInt(Compute_ptr);
var b = Memory.readInt(Compute_ptr.add(4));
console.log("Compute<int> add(" + a + "," + b + ");")
}, onLeave: function (retval) {
//retval.replace(888);
}
});
}
C++11的lambda表达式
格式:[捕捉列表](参数)mutable->返回值类型(函数体)
1、捕捉列表[]足lambda的引出符,捕捉列表能够捕捉上下文中的变量,来供lambda函数使用:
[var]表示以值传递方式捕机变量var,[=]表示值传递捕捉所有父作用域变量,[&var]表示以引用传递方式捕捉变量var,[&]表示引用传递捕捉所有父作用域变量,[this]表示值传递方式捕捉当前的this指针还有一些组合:
[=,&a]表示以引用传递方式捕捉a,值传递方式捕捉其他变量
注意:捕捉列表不允许变量重复传递,如:[=,aj]°6[&,&this],会引起编译时期的错误.
参数列表与普通函数的参数列表一致。如果不需要传递参数,可以联连同()一同【省略】。mutable可以取消Lambda的常量属性,因为Lambda默认是const属性; multable仅仅是让Lamdba函数体修改值传递的变量,但是修改后并不会影响外部的变量。
返回类型如果是void时,可以连->一起【省略】,如果返回类型很明确,可以省略,让编译器自动推倒类型。
函数体和普通函数一样,除了可以使用参数之外,还可以使用捕获的变量。
int b(){
int a =10;
auto add=[](int num)->int{
int res=0;
for(int i=0;i<num;i++){
res=res+i;
}
return res;
};
int res =add(a);
//第二种:
int res=[](int num)->int{
int res=0;
for(int i=0;i<num;i++){
res=res+i;
}
return res;
}(10);
//第三种
int res=[](int num){
int res=0;
for(int i=0;i<num;i++){
res=res+i;
}
return res;
}(10);
//第四种:
int a =10;
int res=[a]{
int res=0;
for(int i=0;i<a;i++){
res=res+i;
}
return res;
}();
}
int c(){
int a =10;
int b=20;
auto change=[a]()mutable{//a的值不会被改变
a=20;
return a;
}
auto change=[&a]{
a=20;
return a;
}
auto change=[&]{
a=20;
b=30;
return a+b;
}
}