美文网首页NDK开发
NDK----C++篇(三)C++ 类

NDK----C++篇(三)C++ 类

作者: 初夏的雪 | 来源:发表于2021-06-17 09:32 被阅读0次

C++ 是面向对象的编程语言,那什么是面向对象呢?一切皆对象,而类就是我们说的对象的类型,所以这也是C++的最最重要的内容,我们今天就开始一点一点的学习。

一、类基本的几个函数(构造函数,析构函数,拷贝构造函数)

说明:

1、如果没有写构造函数,那么创建对象时,默认调用无参数构造函数,若声明了构造函数,则创建对象不会调用默认构造函数

2、析构函数在调用delete后会自动调用,在析构函数中做是否的工作

3、C语言中的malloc 与free 并不会调用构造和析构函数,

4、new/delete 是一套 会调用构造函数 与 析构函数 【C++标准规范】

**malloc/free是一套  不调用构造函数 与 析构函数 【C的范畴,虽然不推荐,但是也是可以的】**

5、拷贝构造函数默认是有的,一旦我们自己写了拷贝构造函数就会覆盖默认的拷贝构造函数

6、拷贝构造函数只有在创建对象时赋值才会被调用,如果对象创建好后再去赋值,则会走默认的赋值来完成

7、如果定义的类的成员时对象成员,必须要在构造函数中这样初始化(构造函数后面 :+对象成员(内容))

先来看看我们自定义一个类:

class Student {
public:
    //公有域
    Student() {
        //无参数构造函数,默认构造,可以不写
        cout << "无参数构造函数" << endl;
    }

    //带参数构造函数,
    Student(string name, int age) : name(name), age(age) {
        cout << "带参数构造函数" << endl;
        cout << "带参构造函数:" << "name=" << name << ",age=" << age << endl;
    }

    //拷贝构造函数
    Student(const Student &student) {
        cout << "拷贝构造函数" << endl;
        this->name = student.name;
        this->age = student.age;
        cout << "拷贝构造函数:" << "name=" << name << ",age=" << age << endl;
    }

    //析构函数,用在在对象被delete时,释放资源
    ~Student() {
        cout << "析构函数" << endl;
    }

protected:
    //半公有域
private:
    //私有域
    string name;
    int age;
};

int main(){
    
     /**
     * 4、误区
     * 指针的赋值不会执行构造函数,因为他仅仅是指针变量指向的问题,也就是指向同一个地址而已
     */
    cout << "误区----演示" << endl;
    Student *zhangsan = new Student("张三", 33);
    Student *lisi = zhangsan;
    cout << endl;


    /**
     * 3、拷贝构造函数
     */
    cout << "拷贝构造函数----演示" << endl;
    Student org_Student("leon", 18);
    Student copy_Sdu = org_Student;//会调用拷贝构造函数
    cout << endl;

    /**
     * 下面不会走拷贝构造函数,只会调用默认的赋值
     */
    Student copy_Sdu2;
    copy_Sdu2 = org_Student;
    cout << endl;

    /**
     * 2、带参构造函数
     */
    cout << "带参构造函数----演示" << endl;
    Student *leon_Student = new Student("leon", 18);
    delete leon_Student;
    leon_Student = NULL;
    cout << endl;
    
     /**
     * 1、默认构造函数与析构函数
     */
    cout << "默认构造函数与析构函数----演示" << endl;
    Student *student = new Student();
    delete student;
    student = NULL;
    return 0;
}

上面的代码注释写的很清楚了,就不啰嗦了,自己拿去允许一下,体会体会就懂了。

二、类的静态成员、方法与友元函数

说明:

1、类的static(成员与函数)通过类名+::来访问,不属于对象

2、类的static 成员不能直接赋值,会报错。例如: static int age = 9;

3、静态的属性必须要初始化,然后再实现(规则)

4、静态方法不能调用非静态方法和成员;非静态函数可以调用静态或非静态的方法和成员;

5、静态成员和方法在.h中声明时需要static,在.cpp文件中不需要,和普通方法一样了;

6、友元函数(好朋友关系,所以可以访问私有成员):在.h中声明时,需要用friend来声明,在.cpp中则不需要friend ,也不需要类名+:: ,只需要函数名,返回,参数即可

7、友元关系不传递(例如:A和B是好朋友,B和C是好朋友,那么A和C就不一定是好朋友)

示例代码:

// 静态demo
class Student {
public:
    static int age;
    char *sex;

    static void show() {
        age = 100;
//        update();  //静态函数不能调用非静态函数,
//        sex="m";  //静态函数不能访问非静态的成员
    }

    void update() {
        int value = age * 10;
        show();
    }
};


//友元demo
class ImageView {
private:
    int width = 100;
    int height = 110;
    string url = "hello";

    friend class Activity;//Activity类是ImageVIew的好友
};

class Activity {
private:
    ImageView img;
    int index;

public:
    void getInfos() {
        cout << "通过友元访问对象的私有成员:width= " << img.width << ",height=" << img.height << ",url=" << img.url << endl;
    }

    // 定义友元函数 (声明,没有实现)
    friend void updateInfos(Activity &activity, int width, int height, string url);
};

void updateInfos(Activity &activity, int width, int height, string url) {
//    activity->img.width=width;//不传递关系
    activity.index = 100;
    cout << "友元函数访问私有成员index=" << activity.index << endl;
}


int main() {

    Activity activity;
    activity.getInfos();

    updateInfos(activity, 0, 0, "");

    return 0;
}

三、类的继承(多继承、虚继承)

说明:

1、多继承,若多个父类拥有想到的成员或方法,编译时会导致二义性( error: request for member 'show' is ambiguous)

  **解决二义性的方法:**

          **1.1) 重写二义性方法;**

         **1.2) 通过.来指明父类,再通过:: 来调用二义性的方法     格式:对象.父类名::函数名**

         **1.3) 虚继承:为多个父类重名的成员和方法提取到一个新的祖父类中(即 虚基类)**

2、继承关系:

默认的的继承关系是private;可以显式指定继承关系,public ,private ,protected

  **1)    private 继承:子类内部仅能访问父类非私有的成员和方法,子类对象不能访问父类的所有成员和方法;**

   **2)   protected 继承:子类内部仅能访问父类非私有的成员和方法,子类对象不能访问父类的所有成员和方法;**

  **3)    public 继承:子类内部仅能访问父类非私有的成员和方法,子类对象可以访问父类的public成员和方法;**

小结:

      **继承后,子类内部只能范文父类的非私有成员和方法,外部之类对象只有在public继承时可以访问父类的public成员和方法,其他都不可以访问**

3、继承关系的构造析构函数的调用顺序

  **构造函数:先调用父类,再调用子类;**

    **析构函数:先调用子类,再调用父类;**

多继承 示例代码:

//多继承
class Base1 {
public:
    void show() {
        cout << "Base1::show()" << endl;
    }
};

class Base2 {
public:
    void show() {
        cout << "Base2::show()" << endl;
    }
};

class MainActivity : public Base1, public Base2 {
public:

    /**
     * 覆盖父类的方法
     */
    void show() {
        cout << "mainActivity::show()" << endl;
    }
};


int main(){
    MainActivity mainActivity;
    mainActivity.show();
    mainActivity.Base1::show();
    return 0;
}

虚继承 示例代码:

//虚继承
class GrandParent {
public:
    char *name;
    int age;
    char *familyName;
};

class Father : virtual public GrandParent {

};

class Mother : virtual public GrandParent {

};

class Child : public Father, public Mother {

};

int main(){
    Child child;
    child.name = "xiaoming";
    cout << "虚继承后,child 的name=" << child.name << endl;
    return 0;
}

四、类的多态(虚函数)

说明:

多态(虚函数):程序在允许期间才能确定调用哪个类的函数 ,这就是动态多态的范畴;

1、概念:父类的引用指向子类的对象,同一个方法有不同的实现,重写(动态多态:运行时确定)和 重载(静态多态:编译期确定);

2、java 默认支持多态的,而C++的多态默认是关闭掉了的, 那我们需要需要在父类的函数上加上virtual 关键字即可打开;

3、创建子类实例时,可以用父类对象来接受;

示例代码:

//多态的demo
class BaseActivity {
public:
    virtual void onCreate() {
        cout << "BaseActivity:onCreate()" << endl;
    }
};


class HomeActivity : public BaseActivity {
public:
    //重载:静态多态
    void onCreate() override {
        cout << "MainActivity:onCreate()--override" << endl;
    }
};

class PersonActivity : public BaseActivity {
public:

    //重写了:动态多态
    void onCreate() {
        cout << "PersonActivity:onCreate()" << endl;
    }
};

void gotoActivity(BaseActivity *baseActivity) {
    baseActivity->onCreate();
}


int main(){
    BaseActivity * homeActivity = new HomeActivity();
    BaseActivity * personActivity = new PersonActivity();
    gotoActivity(homeActivity);
    gotoActivity(personActivity);
    delete homeActivity;
    delete personActivity;
    return 0;
}

五、抽象类与纯虚函数

说明:

1、C++ 没有抽象类,但是有纯虚函数,就相当于Java的抽象类;

2、纯虚函数是必须要继承的,而虚函数则不是必须继承;

3、纯虚函数和虚函数的区别是:纯虚函数没有实现,直接赋值=0 即可;虚函数是有实现的;

4、如果子类没有实现纯虚函数,那么该子类是无法实例化的(即:子类就是抽象类,编译期就会报错);

5、纯虚函数的格式:virtual void getLayoutID()=0;

6、如果一个类的所有的方法都是纯虚函数,那么这个类就等价于java的接口;

7、有存续函数的类无法实例化,编译期会报错;

示例代码:

//全部是纯虚函数---类似于interface
class BaseBaseActivity{
public:
    virtual void onCreate()=0;
    virtual int getLayoutID()=0;
};

//有纯虚函数---抽象类
class BaseActivity : public BaseBaseActivity {
public:
    virtual void onCreate() {
        cout << "BaseActivity:onCreate()" << endl;
    }
    //纯虚函数,如果加上这句话,子类没有实现该纯虚函数,那么该子类是无法实例化的
    virtual int getLayoutID()=0;
};


//
class HomeActivity : public BaseActivity {
public:
    //重载:静态多态
    void onCreate() override {
        cout << "MainActivity:onCreate()--override" << endl;
    }
    //纯虚函数的实现
    int getLayoutID(){
        return 1;
    }
};

class PersonActivity : public BaseActivity {
public:

    //重写了:动态多态
    void onCreate() {
        cout << "PersonActivity:onCreate()" << endl;
    }

    //纯虚函数的实现
    int getLayoutID(){
        return 2;
    }
};

void gotoActivity(BaseActivity *baseActivity) {
    baseActivity->onCreate();
}

int main(){
    
    BaseActivity * homeActivity = new HomeActivity();
    BaseActivity * personActivity = new PersonActivity();
    gotoActivity(homeActivity);
    gotoActivity(personActivity);
    delete homeActivity;
    delete personActivity;
    
    
    return 0;
}

本章内容是非常非常重要的,一定要熟记熟用。。。。。。

本章内容是非常非常重要的,一定要熟记熟用。。。。。。

本章内容是非常非常重要的,一定要熟记熟用。。。。。。

下节预告:运算符重载

相关文章

网友评论

    本文标题:NDK----C++篇(三)C++ 类

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