【C++知识点】继承

简介: 【C++知识点】继承

继承

三种继承方式

不同的继承方式会影响基类成员在派生类中的访问权限。

public继承方式

  1. 1.基类中所有 public 成员在派生类中为 public 属性;
  2. 2.基类中所有 protected 成员在派生类中为 protected 属性;
  3. 3.基类中所有 private 成员在派生类中不能使用。

派生类可以访问基类的 public、protected 成员,不可以访问基类的 private 成员;派生类对象可以访问基类的public成员,不可以访问基类的protected、private成员。

protected继承方式

  1. 1.基类中的所有 public 成员在派生类中为 protected 属性;
  2. 2.基类中的所有 protected 成员在派生类中为 protected 属性;
  3. 3.基类中的所有 private 成员在派生类中不能使用。

派生类可以访问基类的 public、protected 成员,不可以访问基类的 private 成员;派生类对象不可以访问基类的 public、protected、private 成员。

重点

1.派生类从基类那里继承了什么?

  1. 基类的公有成员将成为派生类的公有成员,基类的私有对象也将成为派生类的一部分,但只能通过基类的公有和保护方法访问。

2.派生类不能从基类那里继承什么?

  • 构造函数
  • 赋值运算符
  • 析构函数
  • 友元

菱形继承

案例

// 间接基类A
class A{
protected:
    int m_a;
};
// 直接基类B
class B: public A{
protected:
    int m_b;
};
// 直接基类C
class C: public A{
protected:
    int m_c;
};
//派生类D
class D: public B, public C{
public:
    void seta(int a)
    {
        //m_a = a; //命名冲突
        A::m_a = a; //命名不再冲突
    }
    void setb(int b){
        m_b = b; //正确
    }
    void setc(int c){
        m_c = c; //正确
    } 
    void setd(int d){
        m_d = d; //正确
    } 
private:
    int m_d;
};
int main(){
    D d;
    return 0;
}

虚继承

在 C++ 中,在使用 多继承 时,如果发生了 菱形继承,那么就会出现数据冗余的问题,为了解决菱形继承出现的数据冗余的问题,C++ 提出了虚继承,虚继承使得派生类中只保留一份间接基类的成员。

语法

class B: virtual public A{ //虚继承
};

案例

// 间接基类A
class A{
protected:
    int m_a;
};
// 直接基类B
class B: virtual public A{
protected:
    int m_b;
};
// 直接基类C
class C: virtual public A{
protected:
    int m_c;
};
//派生类D
class D: public B, public C{
public:
    void seta(int a){
        m_a = a; //正确
    }
    void setb(int b){
        m_b = b; //正确
    }
    void setc(int c){
        m_c = c; //正确
    } 
    void setd(int d){
        m_d = d; //正确
    } 
private:
    int m_d;
};

虚继承构造函数

在 C++ 中,普通的 继承 时,可以在子类直接显式的调用父类的 构造函数,在 虚继承 中,虚基类是由最终的派生类初始化的。

也就是说,最终派生类的构造函数必须要调用虚基类的构造函数。对最终的派生类来说,虚基类是间接基类,而不是直接基类。这跟普通继承不同,在普通继承中,派生类构造函数中只能调用直接基类的构造函数,不能调用间接基类的。

// 间接基类A
class A{
public:
    A(int a):m_a(a){}
protected:
    int m_a;
};
// 直接基类B
class B: virtual public A{
public:
    B(int a, int b):A(a), m_b(b){}
    void display()
    {
        cout << "Call B m_a = " << m_a << ", m_b = " << m_b <<endl;
    }
protected:
    int m_b;
};
// 直接基类C
class C: virtual public A{
public:
    C(int a, int c):A(a), m_c(c){}
    void display()
    {
        cout << "Call C m_a = " << m_a << ", m_c = " << m_c <<endl;
    }
protected:
    int m_c;
};
//派生类D
class D: public B, public C{
public:
    // a最终会初始化为50,而不是90和100
    D(int a, int b, int c, int d):A(a), B(90, b), C(100, c), m_d(d){}
    void display()
    {
        cout << "Call D m_a = " << m_a << ", m_b = " << m_b << ", m_c = " << m_c << ", m_d = " << m_d << endl;
    }
    void seta(int a){
        m_a = a; //正确
    }
    void setb(int b){
        m_b = b; //正确
    }
    void setc(int c){
        m_c = c; //正确
    } 
    void setd(int d){
        m_d = d; //正确
    } 
private:
    int m_d;
};
int main(){
    B b(10, 20);
    b.display();
    C c(30, 40);
    c.display();
    D d(50, 60, 70, 80);
    d.display();
    return 0;
}
目录
相关文章
|
4月前
|
编译器 C++
【C++】详解C++的继承
【C++】详解C++的继承
|
1月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
81 11
|
1月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
53 1
|
1月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
39 1
|
1月前
|
安全 编译器 程序员
C++的忠实粉丝-继承的热情(1)
C++的忠实粉丝-继承的热情(1)
18 0
|
1月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
30 0
|
1月前
|
程序员 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
32 0
|
2月前
|
C++
C++(二十)继承
本文介绍了C++中的继承特性,包括公有、保护和私有继承,并解释了虚继承的作用。通过示例展示了派生类如何从基类继承属性和方法,并保持自身的独特性。此外,还详细说明了派生类构造函数的语法格式及构造顺序,提供了具体的代码示例帮助理解。
|
2月前
|
C++
c++继承层次结构实践
这篇文章通过多个示例代码,讲解了C++中继承层次结构的实践应用,包括多态、抽象类引用、基类调用派生类函数,以及基类指针引用派生类对象的情况,并提供了相关的参考链接。
|
3月前
|
安全 Java 编译器