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