C++入门(4)

这篇博客深入探讨了C++中的继承,包括继承的三种方式(public、protected、private)及其对子类访问属性的影响,以及构造析构顺序。还讨论了同名成员函数和变量的处理,赋值兼容性原则,并介绍了虚继承和虚基类的概念,解决菱形继承问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欢迎加入QQ:498903810 一起交流、讨论知识,里面有大佬,也有小白,天下码农一家亲,大家一起讨论进步。

细说继承

感觉上一篇博客对于继承说的不够详细,所以我在这一篇再详细的说一下继承。

现在给大家详细说一下继承的方式:public、protected、private。

public (父类访问级别)protected (父类访问级别)private (父类访问级别)
public (继承方式)publicprotected
protected (继承方式)protectedprotected
private (继承方式)privateprivate

在来介绍以下单个类的访问控制:

public:修饰的成员变量方法,在类的内部类的外部都能使用。

protected:修饰的成员变量方法,在类的内部使用,在继承的子类中可以使用,不能在类的外部使用。

private:修饰的成员变量方法,只能在类的内部使用,不能在类的外部使用。

C++中的继承方式会影响子类的对外访问属性。

public继承:父类成员在子类中保持原有访问级别。

protected继承:父类中public成员会变成protected

​ 父类中protected成员仍然为protected

​ 父类中private成员仍然为private

private继承:父类成员在子类中变成private成员。

父类private成员在子类中仍然存在,但是却无法访问,无论那种方式继承,派生类(子类)都不能直接使用基类的私有成员。

继承主要影响父类的属性在子类的子类的是否可以访问。如果是public继承,子类的子类(孙子类)仍然可以从子类里继承得到父类的属性,并且可以访问且类外也可以访问,如果是protected继承那么子类外将不可以访问。但是仍然可以让孙子类去继承子类在孙子类内去使用,在孙子类外不能访问。如果是private继承,那么子类里可以使用,但是子类的类外不能使用,且孙子类继承子类之后不能访问父类的属性和方法。

差不多就是这些了,继承方式影响的不仅仅是子类,还会对孙子类类有影响。

大多数继承都是public继承

子类、父类、子类普通成员变量的构造析构顺序

构造顺序:父类构造—子类成员变量构造—子类构造

析构顺序:子类析构—子类成员变量析构—父类析构

代码:
#include <iostream>

using namespace std;

class member
{
public:
    member()
    {
        cout << "普通类的构造函数" << endl;
    }
    ~member()
    {
        cout << "普通类的析构函数" << endl;
    }
};
class parent
{
public:
    parent()
    {
        cout << "父类的构造函数" << endl;
    }
    ~parent()
    {
        cout << "父类的析构函数" << endl;
    }
};
class son: public parent
{
public:
    son()
    {
        cout << "子类的构造函数" << endl;
    }
    ~son()
    {
        cout << "子类的析构函数" << endl;
    }
private:
    member m;
};
int main()
{
    son s1;
    return 0;
}
运行结果:
父类的构造函数
普通类的构造函数
子类的构造函数
子类的析构函数
普通类的析构函数
父类的析构函数

继承中同名的成员函数、成员变量

1、重名的数据成员:不加域作用符,默认修改子类的成员变量。

2、重名的成员函数:不加域作用符,默认调用子类的成员变量。

如果想要调用父类的成员函数,需要加类的域作用符号。

例:Parent::date;

就可以访问父类的成员变量了。

#include <iostream>

using namespace std;

class Parent
{
public:
    Parent()
    {
        date = 1;
    }
    void print()
    {
        cout << "parent date = " << date<< endl;
    }
    int date;
};
class Son:public Parent
{
public:
    Son()
    {
        date = 0;
    }
    void print()
    {
        cout << "son date = "<< date << endl;
    }
    int date;
};

int main()
{
    Son s;
    s.date =10;
    s.print();
    return 0;
}
运行结果:
son date = 10

同名隐藏(重定义,继承关系中存在)

父类子类中有同名的函数(参数无所谓),子类继承父类后,用子类调用与父类的同名函数,父类的所有的同名函数都会隐藏,子类不能调用到父类的同名函数。程序会报错。

解决:加父类的域作用符;或者添加命名空间。

#include <iostream>

using namespace std;

class Parent
{
public:
    Parent()
    {
        date = 1;
    }
    void print()
    {
        cout << "parent date = " << date<< endl;
    }
    void print(int a = 1)
    {
        cout << "paretn a = " << a << endl;
    }
    int date;
};
class Son:public Parent
{
public:
    Son()
    {
        date = 0;
    }
    void print()
    {
        cout << "son date = "<< Parent::date << endl;
    }
    int date;
};

int main()
{
    Son s;
    s.date =10;
    s.print(1);//会报错,同名隐藏
    return 0;
}
运行结果:
程序不会运行成功,同名隐藏。解决方法,加类的域作用符。

赋值兼容性原则

类型兼容规则是指在需要基类对象的任何地方,都可使用公有派生类的对象来替代,通过公有继承,派生类得到了基类中除构造函数、析构函数之外的所有成员,这个公有派生类实际就好具备了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决,类型兼容性规则中所指的替代包括以下情况。

子类对象可以当作父类对象使用

子类对象可以直接复制给父类对象

子类对象可以直接初始化父类对象

父类指针可以直接指向子类对象

父类引用可以直接引用子类对象

在替代之后,派生类对象就可以作为基类的对象使用,但是只能使用从基类继承的成员,类型兼容规则是多态性的重要基础之一。

向上转换:派生类对象赋值给基类

向下转换:基类对象赋值给派生类(特殊情况使用)

规范:类名首字母大写; 变量必须小写; 函数如果拥有只读属性,加const。

虚继承和虚基类

虚继承:在继承定义中包含了virtual关键字的继承关系。

虚基类:在虚继承体系中的通过virtual继承而来的基类。

关键字:virtual

虚基类和普通基类的构造顺序:

构造顺序:虚基类—>普通基类

析构顺序:普通基类—>虚基类

  1. 什么是多重继承?
    答:同时继承多个父类
  2. 多重继承有什么?
    答:菱形继承/钻石继承。
  3. 什么是菱形继承/钻石继承?
    答:多重继承的两个或多个父类具有相同的祖先类。
  4. 菱形继承/钻石继承有什么危害?
    答:因为多重继承的两个或多个父类具有相同的祖先类。所以会有完全相同的属性和方法。因此当前多重继承类有两份相同的属性和方法。使用时会出现冲突。
  5. 如何解决菱形继承/钻石继承导致的冲突?
    答:使用虚继承。
  6. 什么是虚继承?
    答:父类在继承具有相同的祖先类时,加上virtual
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值