Android NDK开发之旅22--C++--面向对象

前言

C++是面向对象的编程语言,因此有类的概念。下面介绍面向对象中一些比较重要的知识点。

继承

继承主要是提高代码的重用性。

下面是一个继承的例子:

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

private:
    char* name;
    int age;
};

class Woman :public Human{
public:
    Woman(char* name, int age, float weight)
        //指定调用父类的哪一个构造函数、初始化属性对象
        :Human(name, age), m(name, age)
    {
        this->weight = weight;
    }
    void shopping(){
        cout << "购物" << endl;
    }
    void say(){
        cout << "女人说话" << endl;
    }
private:
    float weight;
    Human m;
};

void main(){
    Woman w("haha", 20, 90.0);
    system("pause");
}

需要注意的地方有:

  1. 通过:public来继承Human。
  2. 通过在自身构造的时候给父类构造函数传参。(同时给属性对象赋值)因为子类构造的时候,会先构造父类。
  3. 构造与析构的调用顺序:构造的时候先调用父类的构造函数,然后调用子类的构造函数。析构的时候相反。总结就是,先构造,先释放。
  4. 上面的继承中,子类覆盖了父类的say方法,但是这并不是多态(没有virtual关键字)。只是父类的say方法被隐藏了。子类可以对象调用父类的方法。

例如,我们可以通过下面的方式去指定调用父类还是子类的方法:

void work(Human &m){
    m.say();
}

void main(){
    Woman w("haha", 20, 90.0);

    //调用子类的say方法(这两种实质是一样)
    w.say();
    w.Woman::say();

    //调用父类的say方法(显示指明,或者用子类去初始化父类的时候)
    w.Human::say();
    Human h = w;
    h.say();
    work(w);

    system("pause");
}

例如Java中就无法使用被覆盖的父类方法了,但是通过JNI的方式可以访问到。

继承的访问修饰符

主要的规律就是,两个之中的最小值。

基类中      继承方式             子类中
public     & public继承        => public
public     & protected继承     => protected   
public     & private继承       => private

protected  & public继承        => protected
protected  & protected继承     => protected   
protected  & private继承       => private

private    & public继承        => 子类无权访问
private    & protected继承     => 子类无权访问
private    & private继承       => 子类无权访问

补充说明:

  1. public关键字能够在类本身、子类、类以外的地方使用。
  2. protect关键字只能够在 类本身、子类 中使用。
  3. private关键字只能够在 类本身 中使用。

多继承

多个父类通过,隔开:

class Person{

};

//公民
class Citizen{

};

//学生,既是人,又是公民
class Student : public Person, public Citizen{

};

多继承的二义性问题

class A{
public:
    char* name;
};

class A1 : public A{
    
};

class A2 : public A{

};

class B : public A1, public A2{

};

void main(){
    B b;

    //这句话编译不通过,因为存在二义性
    b.name = "3";

    //B中有两个name的副本,我们可以指定使用哪个父类的name
    b.A1::name = "1";
    b.A2::name = "2";

    system("pause");
}
继承的二义性.png

问题:B中有两个name的副本。但是我们一般情况下只需要一份。

解决办法:虚继承,不同路径继承来的同名成员只有一份拷贝,解决不明确的问题:

如果某个类B的两个父类(A1、A2)都继承于同一父类(A),那么这两个父类(A1、A2)可以通过在继承的时候加上virtual关键字来解决二义性问题:

class A{
public:
    char* name;
};

class A1 : virtual public A{

};

class A2 : virtual public A{

};

class B : public A1, public A2{

};

void main(){
    B b;
    //这时候name的副本只有一份了
    b.name = "3";

    system("pause");
}

多态

多态的作用:程序的扩展性
继承的作用:程序的重用性

多态分类:

  1. 动态多态:程序运行过程中,觉得哪一个函数被调用(重写)。
  2. 静态多态:重载。

这里主要讨论动态多态,动态多态的条件:

  1. 继承
  2. 父类的引用或者指针指向子类的对象
  3. 函数的重写(需要增加virtual关键,否则的话就是覆盖)

简单的例子,注意添加virtual关键字(虚函数):

class Human
{
public:
    virtual void say(){
        cout << "人说话" << endl;
    }
};

class Woman :public Human{
public:
    virtual void say(){
        cout << "女人说话" << endl;
    }
};

class Man :public Human{
public:
    virtual void say(){
        cout << "男人说话" << endl;
    }
};

void say(Human &h){
    h.say();
}

void main(){
    Woman w;
    Man m;

    say(w);
    say(m);

    system("pause");
}

纯虚函数

纯虚函数(抽象类)

  1. 当一个类具有一个纯虚函数,这个类就是抽象类
  2. 抽象类不能实例化对象
  3. 子类继承抽象类,必须要实现纯虚函数,如果没有,子类也是抽象类

抽象类(逻辑上就是Java中的接口)的作用:为了继承约束(新增加的类必须实现父类,提高代码重用性,保证系统的条理性、封闭性),根本不知道未来的实现(例如JDBC中的驱动就是接口)

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 main(){
    //Shape s;抽象类不能创建对象
    Circle c(10);

    system("pause");
}

C++中的接口是按照逻辑上区分出来的,不像Java中有专门的interface关键字。例如在C++中我们可以把只有纯虚函数的类看做一个接口:

class Drawble{
    virtual void draw();
};

如果觉得我的文字对你有所帮助的话,欢迎关注我的公众号:

公众号:Android开发进阶

我的群欢迎大家进来探讨各种技术与非技术的话题,有兴趣的朋友们加我私人微信huannan88,我拉你进群交(♂)流(♀)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容