美文网首页
C++继承,静态成员,const成员

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

作者: lieon | 来源:发表于2020-11-05 18:13 被阅读0次

继承

继承的方式有三种

  • 公共继承
  • 保护继承
  • 私有继承
访问权限 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://img.haomeiwen.com/i5456635/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指针只能用在非静态成员函数内部)
    • 不能是虚函数(虚函数只能是非静态成员函数)
    • 内部不能访问非静态成员变量\函数,只能访问静态成员变量\函数
    • 非静态成员函数内部可以访问静态成员变量\函数
    • 构造函数,析构函数不能是静态
    • 当声明和实现分离时,实现不能带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) {};
};

相关文章

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

    继承 继承的方式有三种 公共继承 保护继承 私有继承 访问权限publicprotectedprivate对本类可...

  • c++语法2

    接上篇我们继续学习静态成员、友元函数、继承、多重继承,继承访问权限等 静态成员与友元函数:c++中静态成员与jav...

  • C++中对Const用法的总结

    1、C++函数声明时在后面加const的作用:非静态成员函数后面加const(加到非成员函数或静态成员后面会产生编...

  • 19-const成员

    const成员 const成员:被const修饰的成员变量,非静态成员函数 像在平时开发中,可以通过以下的方式来定...

  • C++

    框架: 构造函数: 继承中的访问控制: 不允许重载的符号: 成员指针与成员函数指针: const的限定: 类中静态...

  • C++ const用法

    一 修饰类 C++中const修饰类主要包括3个部分:数据成员,成员函数,对象。 数据成员const 修饰类的成员...

  • C++的const复习

    复习:如何访问静态成员 复习: const 修饰函数参数 复习:const 修饰成员函数(const的作用:说明其...

  • GeekBand.重学C++(4)

    关于 this 指针 调用父类的成员 非 const 成员中 const 成员中 动态绑定与静态绑定 绑定时期 动...

  • C++笔记

    2. Const 和 Static Const相关注意 ◼ 静态成员:被static修饰的成员变量\函数​ ...

  • C++中的成员变量和成员函数

    C++中的类有两个成分: (1)成员变量 成员变量按照作用域分为静态成员变量和非静态成员变量,C++中成员变量的默...

网友评论

      本文标题:C++继承,静态成员,const成员

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