NDK开发:C++基础

作者: 小村医 | 来源:发表于2019-09-18 21:47 被阅读0次

一、命名空间

standard:标准命名空间

using namespace std;

命名空间类似于java中的包。

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

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

  1. 使用命名空间
cout << NSP_A::a << endl;
cout << NSP_B::a << endl;
cout << NSP_B::NSP_C::c << endl;
//使用命名空间中的结构体
using NSP_A::Student;
Student t;
t.age = 90;

::为访问修饰符

二、引用

引用是变量的别名(内存空间0x00001的别名),指针是变量的地址

int a = 10;
// b是内存空间的另一个别名
//& C++中的引用
int &b = a;
  1. 使用指针交换数据
void swap(int *a, int *b){
    int c = 0;
    c = *a;
    *a = *b;
    *b = c;
}
  1. 使用引用交换数据
void swap(int &a, int &b){
    int c = 0;
    c = a;
    a = b;
    b = c;
}

引用的主要功能:作为函数的参数或返回值,引用必须有值,不能为空
单纯给变量取别名没有任何意义,作为参数传递,能保证参数传递过程中不产生副本;
引用可以直接操作变量,指针要通过取值(*p),间接操作变量,指针的可读性差。

  1. 指针的引用代替二级指针
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;
}
  1. 指针常量/常量指针

指针常量:不改变地址的指针,但是可以修改指针指向的内容

int a = 2, b = 3;
int *const p = &a;
p = &b; //不能重新赋值
*p = 4; 可以改变指向的内容

常量指针:指向常量的指针,内容不能修改

const int *p = &a;
p = &b;
//*p2 = 9;  //不能改变内容

三、函数

  1. C++中函数可以有默认值
void customPrint(int x, int y = 9, int z = 8){
    cout << x << endl;
}
  1. 可变参数
#include <stdarg.h>
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 func(int i,...){
    va_list args_p;
    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);
}

四、类

  1. 定义头文件
#pragma once
class Person{
public:
    int age;
    char* name;
public:
    void setAge(int age);
    int getAge();
    void setName(char* name);
    char* getName();
};
  1. 实现头文件定义的函数
#include "Person.h"

void Person::setAge(int age){
    this->age = age;
}

int Person::getAge(){
    return this->age;
}

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

char* Person::getName(){
    return this->name;
}
  1. 使用类
#include "Person.h"
void main(){
  Person person;
  person.name= "Jack";
}
  1. 构造函数
class Person{
private:
    char *name;
    int age;
public:
    //无参改造函数(会覆盖默认的无参构造函数)
    Person(){
        cout << "无参构造函数" << endl;
    }
    // 有参构造
    Person(char *name, int age){
        this->name = name;
        this->age = age;
        cout << "有参构造函数" << endl;
    }   
  
};

  1. 析构函数

当对象要被系统释放时析构函数会被调用

~Person(){
    cout << "析构函数" << endl;
    //释放内存
    free(this->name);
}
  1. 拷贝构造函数
class Person{
private:
    char *name;
    int age;
public:
    Person(char *name, int age){
        this->name = name;
        this->age = age;
        cout << "有参构造函数" << endl;
    }
    //拷贝构造函数
    //默认的拷贝构造函数是值拷贝,拷贝的是指针地址
    Person(const Person &obj){
        this->name = obj.name;
        this->age = obj.age;
        cout << "拷贝构造函数" << endl;
    }
};
void main(){
  Person p1("Jack",20);
  Person p2 = p1;
}

输出结果:

有参构造函数
拷贝构造函数

  1. 深拷贝
    覆盖默认的拷贝构造函数,拷贝的是指针指向的内容
 Person(const Person &obj){
    //复制name属性
    int len = strlen(obj.name);
    this->name = (char*)malloc(len+1);
    strcpy(this->name,obj.name);
    this->age = obj.age;
}

拷贝构造函数被调用的场景:

  • 声明时复制
  • 最为参数传入,实参给形参赋值
  • 作为函数返回值返回,给变量初始化赋值
  1. 构造函数的属性初始化列表
class Teacher{
private:
    char* name;
public:
    Teacher(char* name){
        this->name = name;
    }
    ~Teacher(){
        cout << "析构函数" << endl;
    }
    char* getName(){
        return this->name;
    }

};

class Student{
private:
    int id;
    //属性对象
    //Teacher t = Teacher("name");
    Teacher t1;
    Teacher t2;
public:
    Student(int id,char *t1_n, char* t2_n) : t1(t1_n), t2(t2_n){
        this->id = id;
        cout << "Student构造函数" << endl;
    }
    ~Student(){
        cout << "Student析构函数" << endl;
    }
};

五、new/delete动态内存分配

void func(){
    //C++   
    //会调用构造函数和析构函数
    Teacher *t1 = new Teacher("jack");
    cout << t1->getName() << endl;
    //释放
    delete t1;

    //C的写法,不会调用构造函数和析构函数
    //Teacher *t2 = (Teacher*)malloc(sizeof(Teacher));
    //t2->setName("jack");
    //free(t2);
}

数组类型

//C
//int *p1 = (int*)malloc(sizeof(int) * 10);
//p1[0] = 9;
//free(p1);
    
//C++
int *p2 = new int[10];
p2[0] = 2;
//释放数组要加上 []
delete[] p2;

六、静态属性、静态方法

class Teacher{
public:
    char* name;
    //静态成员
    static int total;
public:
    Teacher(char* name){
        this->name = name;      
        cout << "Teacher构造函数" << endl;
    }
}

静态属性初始化赋值

int Teacher::total = 9;

初始化完成后使用

Teacher::total++;

静态函数

static void count(){
    total++;        
    cout << total << endl;
 }

调用静态函数

Teacher::count();

七、类的大小

class A{
public:
    int i;
    int j;
    int k;
};

class B{
public:
    int i;
    int j;
    int k;
    void fun(){
        cout << "fun" << endl;
    }
};

int main(int argc, const char * argv[]) {
    cout<< sizeof(A)<<endl;
    cout<< sizeof(B)<<endl;
    return 0;
}

输出结果:

12
12

C/C++内存分区:栈、堆、全局(静态)、常量去(字符串)、程序代码区
普通属性与结构体相同的内存布局
静态变量存储在全局区
函数存在程序代码区

八、友元函数

class A{
    //友元函数
    friend void modify_i(A *p, int a);
private:
    int i;
public:
    A(int i){
        this->i = i;
    }
};

//友元函数的实现,在友元函数中可以访问私有的属性
void modify_i(A *p, int a){
    p->i = a;
}

九、友元类

class A{
    //友元类
    friend class B;
private:
    int i;
public:
    A(int i){
        this->i = i;
    }

};

class B{
public:
    //友元类可以访问A中的任何成员
    void accessAny(){
        a.i = 30;
    }
private:
    A a;
};

十、运算符重载

class Point{
public:
    int x;
    int y;
public:
    Point(int x = 0, int y = 0){
        this->x = x;
        this->y = y;
    }
    void myprint(){
        cout << x << "," << y << endl;
    }
    //成员函数运算符重载
    Point operator+(Point &p2){
        Point tmp(this->x + p2.x, this->y + p2.y);
        return tmp;
    }
};

//重载+运算符
Point operator+(Point &p1, Point &p2){
    Point tmp(p1.x + p2.x, p1.y + p2.y);
    return tmp;
}

//重载-运算符
Point operator-(Point &p1, Point &p2){
    Point tmp(p1.x - p2.x, p1.y - p2.y);
    return tmp;
}

十一、继承

class Human{
public:
    void say(){
        cout << "say" << endl;
    }
protected:
    char* name;
    int age;
};

//子类
class Man : public Human{
public:
    void work(){
        cout << "work" << endl;
    }
private:
    char* brother;
};
int main(int argc, const char * argv[]) {
    Man man;
    man.say();
    Human *p = &man;
    p->say();    
    return 0;
}

带有参构造函数的继承

class Human{
public:
    Human(char* name, int age){
        this->name = name;
        this->age = age;
    }
    void say(){
        cout << "say" << endl;
    }
protected:
    char* name;
    int age;
};

class Man : public Human{
public:

    Man(char *brother, char *s_name, int s_age, char *h_name, int h_age) : Human(s_name, s_age), h(h_name,h_age){
        this->brother = brother;
    }
    void work(){
        cout << "work" << endl;
    }
private:
    char* brother;
    Human h;
};

多继承

//人
class Person{
    
};

//公民
class Citizen{
    
};

//多继承
class Student : public Person, public Citizen{
    
};

十二、多态

  1. 虚函数实现多态
//Plane.h
class Plane{
public:
    virtual void fly();
    virtual void land();
};
//Plane.cpp
void Plane::fly(){
    cout << "起飞" << endl;
}

void Plane::land(){
    cout << "着陆" << endl;
}
// Helicopter.h
class Helicopter : public Plane{
    virtual void fly();
    virtual void land();
};
// Helicopter.cpp
void Jet::fly(){
    cout << "直升机起飞" << endl;
}

void Jet::land(){
    cout << "直升机着陆" << endl;
}
  1. 纯虚函数(抽象类)
    当一个类具有纯虚函数时,这个类就是抽象类。抽象类不能实例化对象。子类继承抽象类必须实现纯虚函数,如果没有子类也是抽象类
class Shape{
public:
    //纯虚函数
    virtual void sayArea() = 0;
};

class Circle : public Shape{
public:
    Circle(int r){
        this->r = r;
    }
    void sayArea(){
        cout << "圆的面积" << (3.14 * r * r) << endl;
    }
private:
    int r;
};

十三、模板函数(泛型)

void myswap(int& a,int& b){
    int tmp = 0;
    tmp = a;
    a = b;
    b = tmp;
}

void myswap(char& a, char& b){
    char tmp = 0;
    tmp = a;
    a = b;
    b = tmp;
}

上面两个函数业务逻辑一样,数据类型不一样。

template <typename T>
void myswap(T& a, T& b){
    T tmp = 0;
    tmp = a;
    a = b;
    b = tmp;
}

相关文章

网友评论

    本文标题:NDK开发:C++基础

    本文链接:https://www.haomeiwen.com/subject/klucuctx.html