C++继承,虚继承,静态成员,const成员

继承

继承的方式有三种

  • 公共继承
  • 保护继承
  • 私有继承
访问权限 public protected private
对本类 可见 可见 可见
对子类 可见 可见 不可见
对外部(调用方) 可见 不可见 不可见

继承中的对象模型

  • 父类中所有的非静态成员属性都会被子类继承下去
  • 父类中私有成员属性是被编译器给隐藏了,因此访问不到,但确实被继承下去了
struct Person {
public:
    int m_A;
protected:
    int m_age;
private:
    int m_B;
};

struct Student: public Person {
    int m_no;
};

Student 对象占用16个字节

继承中构造和析构的顺序

  • 构造顺序:先构造父类,再构造子类
  • 析构:先析构子类,再析构父类

继承中访问同名的成员

  • 子类对象可以直接访问子类中同名成员
  • 子类对象加作用域可以访问父类同名成员
  • 当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数

多继承

C++允许一个类可以有多个父类

class Student {
public:
    int m_score;
    
    void study() {
       cout << "Student::study" << endl;
    }
};

class Workder {
public:
    int m_salary;
    
    void work() {
        cout << "Workder::work" << endl;
    }con
};

class Undergraduate: public Student, public Workder {
public:
    int m_grade;
    
    void play() {
        cout << "Undergraduate::play" << endl;
    }
};

多继承体系下的构造函数调用

class Undergraduate: public Student, public Workder {
public:
    int m_grade;
    
    Undergraduate(int grade, int score, int salary): Student(score), Workder(salary) {
        m_grade = grade;
    }
};



## 多继承-虚函数
- 如果子类继承多个父类都有虚函数,那么子类对象就会产生对应的多张虚表
  - ![image.png](https://upload-images.jianshu.io/upload_images/5456635-938814dd437afbe3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)

## 同名函数,同名成员变量

```C++


class Student {
public:
    int m_score;
    int m_age;
};

class Workder {
public:
    int m_salary;
    int m_age;
};

class Undergraduate: public Student, public Workder {
public:
    int m_grade;
    int m_age;
    Undergraduate(int grade, int score, int salary): Student(score), Workder(salary) {
        m_grade = grade;
    }
};

void test() {
    Undergraduate ug(10, 10, 1);
    ug.Student::eat();
    ug.Workder::eat();
    ug.eat();
    
    ug.Student::m_age = 29;
    ug.Workder::m_age = 29;
    ug.m_age = 29;
}

菱形继承

  • 菱形继承带来的问题
    • 最低下子类从基类继承的成员变量冗余,重复
    • 最低子类无法访问基类的成员,有二义性
    • image.png
    class Person {
        int m_age;
    };

    class Student: public Person {
    public:
        int m_score;
    };

    class Workder: public Person {
    public:
        int m_salary;
    };

    class Undergraduate: public Student, public Workder {
    public:
        int m_grade;
    };

虚继承

  • 虚继承可以解决菱形继承问题
  • Person称为虚基类
  • Workder的虚表存储的内容有
    • 虚表指针与本类起始的偏移量(一般是0)
    • 虚基类第一个成员与本类起始的偏移量
image.png
class Student: virtual public Person {
public:
    int m_score;
};

class Workder: virtual public Person {
public:
    int m_salary;
};

class Undergraduate: public Student, public Workder {
public:
    int m_grade;
};
image.png
image.png
class Sleep: virtual public Animal { };

class Tuo: virtual public Animal { };

class SleepTuo: public Sleep, public Tuo { };

/*
 Sleep 和 Tuo中通过虚继承存储的是一个vbptr(虚基类指针),该指针分别指向一个Sleep和Tuo的一个虚表,该虚表存储的是SleepTuo中一个地址偏移量
 ,通过该偏移量和vbptr的起始地址,得到最终指向的地址
 Sleep的vbptr指向: 0(起始值)+ 8(偏移量)= 8
 Tuo的vbptr指向: 4(起始值)+ 4(偏移量) = 8
 
 */

静态成员

  • static修饰的成员变量\函数
  • 可以通过对象(对象.静态成员),对象指针(对象指针->静态成员), 类访问(类名::静态成员)
  • 静态成员变量
    • 存储在数据段(全局区,类似于全局变量),整个程序运行过程中只有一份内存
    • 对比全局变量,它可以设定访问权限(public, protected, private),达到局部共享的目的
    • 必须初始化,必须在类外部初始化,初始化不能带static,如果类的声明和实现分离(在实现的.cpp中初始化)
  • 静态成员函数
    • 内部不能使用this指针(this指针只能用在非静态成员函数内部, 非静态函数的自带一个默认参数this,所以能在非静态方法中访问到this的成员变量,但是静态函数没有this指针)
    • 不能是虚函数(虚函数只能是非静态成员函数)
    • 内部不能访问非静态成员变量\函数,只能访问静态成员变量\函数
    • 非静态成员函数内部可以访问静态成员变量\函数
    • 构造函数,析构函数不能是静态
    • 当声明和实现分离时,实现不能带static,包含static关键字的函数只在他所在的文件中是可见的,在其他文件中不可见,会导致找不到定义

静态成员的访问方式

  • 通过类名访问
Perosn::m_age = 30;
  • 通过对象访问
Perosn p;
p.m_age = 0;
class Car {
    int m_price;
    static int ms_count;
public:
    static int getCount() {
        return ms_count;
    }
    
    Car(int price = 0): m_price(price) {
        ms_count++;
    }
    
    ~Car() {
    }
};

静态成员经典应用 - 单例模式

class Rocket {
private:
   static Rocket* ms_instace;
   Rocket() { }
   Rocket(const Rocket &rocket) { };
   Rocket &operator=(const Rocket &rocket) { return *this; };

public:
   static Rocket* shared() {
       // 严格要讲,这段代码需要考虑线程安全的问题
       if (ms_instace == nullptr) {
           ms_instace = new Rocket();
       }
       return ms_instace;
   }
};

Rocket* Rocket::ms_instace = nullptr;

const成员

  • const成员: 被const修饰的成员变量,非静态成员函数
  • const成员变量
    • 必须初始化(类内部初始化),可以在声明的时候直接初始化赋值
    • 非static的const成员变量还可以在初始化列表中初始化
  • const成员函数(非静态)
    • const关键字写在参数列表后面,函数的声明和实现必须带const
    • 内部不能修改费static成员变量
    • 内部只能调用 const 成员函数、 static 成员函数
    • 非const成员函数可以调用const成员函数
  • const成员函数和非const成员函数构成重载
    • 非const对象(指针)优先调用非const成员函数
  • const对象只能调用const成员函数,static函数
  • this指针的本质是指针常量,指针的指向不可以修改的
  • 在成员函数后面添加const,修饰的是this指向,让指针指向的值不可以修改, 常函数内不可以修改成员属性
  • 要在常函数中修改成员变量,可以给这个成员变量加上mutable关键字
class Car {
    const int mc_wheelsCount = 20;
public:
    Car(): mc_wheelsCount(10) {};
    
    void run() const {
        std::cout << "run()" << std::cout;
    }
};

引用类型成员

  • 引用类型成员变量必须初始化(不考虑static情况)
    • 在声明的时候直接初始化
    • 通过初始化列表初始化
class Car {
    int age;
    int m_price = age;

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

推荐阅读更多精彩内容