C++中的继承(一)

这篇具有很好参考价值的文章主要介绍了C++中的继承(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

我们之前说过,继承是面向对象的三大特性。

面向对象的三大特性:
封装、继承、多态。

封装在类和对象体现出。

概念

继承是什么?
继承就是一种类层次的复用,复用就是你的就变成我的.

假设我要实现一个管理系统。
如果按照以前类和对象的方式,单独去实现这个类是很坑的.

每个类都有一些信息, 有些类型之间是有一些共性,
每个类都写,那初始化每个类都要写.
C++中的继承(一),c++,c++,java,jvm

C++创造了一个语法,可以支持继承,支持什么样的继承呢?
把我们公共的属性提取出来,放到一个类里面去,让剩下的类去继承.
C++中的继承(一),c++,c++,java,jvm

我们也可以有些单独独立的信息.

继承是什么样的呢?
首先有很多类。如果这些类都有一些公共的特征,那我们就可以这些
类里面有些特性提取出来,专门放到一个类里面。这个类我们叫做父类。

我们想用这些特征,以前我们要写到一起,我们现在可以继承它。
怎么继承?

我们看一下它的语法:

 //基类/父类
class Person
{
public:
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}

private:  
	string _name = "peter"; // 姓名
	int _age = 18;  // 年龄
};

class Student : public Person
{
protected:
	int _stuid; // 学号
};

继承方式有三种:
公有继承,私有继承,保护继承。

student这个类看起来啥都没有,其实里面啥都有。
C++中的继承(一),c++,c++,java,jvm

它怎么来的?就是从它的父类。
stuent这个类的信息除了有学生的信息还有pesorn的信息,因为它继承了person.
继承也就是父类的我也有。

访问限定符

继承有三种访问限定符,但这三种访问限定符又有三种访问限定方式。
它们两两组合。
C++中的继承(一),c++,c++,java,jvm
这些有什么规律?
它们分成了两组规则。
C++中的继承(一),c++,c++,java,jvm
1.如果是公有成员和保护成员,就取它们继承方式和它的权限里小的那个。(公有大于保护,保护大于私有)
2.私有成员都是不可见。(不可见就是它在这个地方,你不能用)

演示一下,把父类的成员设置成私有
在子类写一个函数。
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm
不可见就是在类里面也用不了,但是它跟私有不一样,私有在类里面可以用。

什么时候我们会定义私有呢?
这东西我不想被子类继承就用私有。

私有和保护在子类才有区别

子类能不能调用父类的函数取访问它?
可以。不可见只是指的是不能直接取访问它,取去调用父类的函数去访问也是可以的。

继承方式也可以像访问限定符一样,可以不写,class默认就是私有继承,struct默认就是公有继承。

实际当中用的最多的,就是这些。
C++中的继承(一),c++,c++,java,jvm

基类和派生类的赋值转换

这是重点中的重点。这块想说的一个问题是什么?
C++中的继承(一),c++,c++,java,jvm
这里会发生什么?d可以赋值给i吗?
可以。发生隐式类型转换,中间会产生临时变量,临时变量具有常性。

接着往下看,一个子类对象能不能给父类对象呢?
C++中的继承(一),c++,c++,java,jvm
可以,但是有没有隐式类型转换的发生呢?
这里只适用于公有继承上,子类可以赋值给父类,这个过程叫做赋值兼容转换。
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm
怎么证明呢?
C++中的继承(一),c++,c++,java,jvm

C++中的继承(一),c++,c++,java,jvm

子类可以赋值给父类,父类能不能给子类?
默认不可以,子类还有一些专有的属性。

继承中的作用域

基类和派生类都有它们独立的作用域。

既然它们都有独立的作用域,那基类和派生类能不能有同名成员呢?
C++中的继承(一),c++,c++,java,jvm

派生类能不能也定义一个_num,可以。
我们c语言就规定不同的作用域可以定义同名的变量。

但是这样,我是会报错还是会访问派生类的呢?
C++中的继承(一),c++,c++,java,jvm

理论上是访问派生类的,根据就近原则。
C++中的继承(一),c++,c++,java,jvm
但是我就想访问基类,有没有什么办法?
指定作用域就可以了,加上域作用限定符。
C++中的继承(一),c++,c++,java,jvm

子类和父类有同名成员,这种情况我们叫做隐藏或者重定义。
隐藏指的是默认情况下他会隐藏父类的成员。

class Person
{
protected:
	string _name = "小李子"; // 姓名
	int _num = 111; 		// 身份证号
};

class Student : public Person
{
public:
	void Print()
	{
		cout << Person::_num << endl;
		cout << _num << endl;
	}

protected:
	int _num = 999; // 学号
};

这里有个很坑的东西,经常出选择题考。
以下程序哪个是对的。
C++中的继承(一),c++,c++,java,jvm
这道题的杀手锏是A,为什么是A?
函数名相同,参数不同构成函数重载。
那现在有一个问题,vector里的push_back和list里的push_back呢?
记住,函数重载必须在同一个作用域里面。

编译也没有报错。
虽然它们参数不同,但是它们的关系确实是隐藏。

最麻烦的考法是这样的。
下面这个选什么。
C++中的继承(一),c++,c++,java,jvm
这道题如果是不定向选择,那就是BC.
如果确实要访问A里的fun, 要指定一下作用域

b.A::func();

结论:
如果是成员函数的隐藏,只需要函数名相同就可以构成隐藏。
不需要考虑参数,不需要考虑返回值。

注意在实际中最好不要定义同名的成员,不然自己坑自己。

派生类的默认成员函数

构造函数

派生类的构造函数时怎么玩的呢?
跟我们以前学的有一点点不一样。
C++中的继承(一),c++,c++,java,jvm

C++中的继承(一),c++,c++,java,jvm
注意看这个派生类,我什么都没有写.发生了啥?
如果我们不写,子类会自动调用父类的成员。

如果我们写了呢?
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm
不可以。为什么呢?

在派生类当中,规定了,父类的成员,必须调父类的构造函数初始化。
你不写它也会调用父类的,你写他也会调用父类的。
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm
上面两个都可以编译通过。
你不写他也会调用父类的默认构造,在初始化列表里调。
继承就像子类把父类当作一个自定义类型的整体成员一样。

那如果父类没有默认构造怎么办?
那我们就必须自己写了,自己显示的调用了。

拷贝构造

拷贝构造和前面也是同样的道理。
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm
可以,但是你自己不写他会不会调用父类的拷贝构造。
不会,要初始化父类怎么办?调用父类的拷贝构造。但是要求调用父类的拷贝构造,
是不是要传一个父类的对象过去。

只有子类对象没有父类对象,如何把子类对象父类这一部分拿出来啊。
我们可以用我们之前讲到的切片。
C++中的继承(一),c++,c++,java,jvm
子类对象我也没有父类的那一部分,但是我可以传过去让它自己切就可以了。
C++中的继承(一),c++,c++,java,jvm

这里回答一下之前遗留下来的一个问题?
如果是子类对象给父类对象,这个地方是怎么给过去的?
C++中的继承(一),c++,c++,java,jvm
是memcpy拷贝过去还是怎么拷贝。
这里还是调用了拷贝构造,调用了父类的拷贝构造。
C++中的继承(一),c++,c++,java,jvm
operatro=也是一样的道理
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm
但是这里出现了一个栈溢出的问题,是怎么回事呢?
栈溢出一般都是重复调用,这里教大家一个技巧,可以看调用堆栈
C++中的继承(一),c++,c++,java,jvm
死循环了。为什么?
因为Student类里面的operator=和Person类里面的operator构成隐藏关系。
所以这里自己调用自己了。
C++中的继承(一),c++,c++,java,jvm
指定作用域就可以了
C++中的继承(一),c++,c++,java,jvm

C++中的继承(一),c++,c++,java,jvm

总结一下就是自己干自己的,父类处理父类的。

可不可以不写拷贝构造和赋值呢?
可以,我们之前说过,拷贝构造针对内置类型进行值拷贝或者浅拷贝,
针对自定义类型会调用它的拷贝构造。

析构函数

特点都是先父后子
C++中的继承(一),c++,c++,java,jvm

C++中的继承(一),c++,c++,java,jvm

但是有个非常奇怪的现象,我们调用不了析构。为什么?
由于以后多态的原因,析构不会用这个名字,
析构函数会被处理成Destructro,所以它们会构成隐藏的关系。
所以还是指定一下。
C++中的继承(一),c++,c++,java,jvm
但是这样也不行,父类的析构被调用了两次。
C++中的继承(一),c++,c++,java,jvm
其它成员函数都可以显示调用,唯独析构函数我们不要显示调用。
它可以自动调用,为什么它可以自动?以为它要保证我们的顺序。
C++中的继承(一),c++,c++,java,jvm
自己显示写不能保证调用先子后父的顺序。

为什么要先析构子类再析构父类?
因为父类先定义,子类后定义。

先析构父类,再析构子类有可能会出现野指针的问题。
C++中的继承(一),c++,c++,java,jvm

继承的其他一些细节

友元关系不能被继承。
比如一个类,一个函数是你父类的友元,那是不是你子类的友元呢?
不是。
C++中的继承(一),c++,c++,java,jvm
但是我就是想访问怎么办?
再定义一个友元就可以了。

class Person
{
public:
	friend void Display(const Person& p, const Student& s);
//protected:
	string _name; // 姓名
};
class Student : public Person
{
	friend void Display(const Person& p, const Student& s);
protected:
	int _stuNum; // 学号
};

void Display(const Person& p, const Student& s)
{
	cout << p._name << endl;
	cout << s._stuNum << endl;
}

void main()
{
	Person p;
	Student s;
	Display(p, s);
}

静态成员是怎么走的?
C++中的继承(一),c++,c++,java,jvm
C++中的继承(一),c++,c++,java,jvm

父类继承有一个_count,子类继承会不会也友一个_count呢?
不会。但是从域的角度,子类可以访问它。

无论你继承多少次,都只有一个_count
静态成员变量属于整个类,它不仅属于父类也属于子类。但是只有同一个。

证明一下:
父类当中的_name和子类当中的_name是不是同一个。
不是,它们的地址是不一样的。
但是_count是同一个。

把父类protected:去掉
C++中的继承(一),c++,c++,java,jvm

下一个问题,这里Peron或者以Peson为继承的子类对象总共创建了多少个对象?
怎么算呢?这里有一个非常巧妙的东西。在父类的构造函数++_count就可以,为什么?
因为子类对象必须调用父类对象去初始化
C++中的继承(一),c++,c++,java,jvm>

静态的成员所有继承的派生类共享。

实现一个不能被继承的类,如何实现?
最简单的方式就是把它的构造函数私有化,或者析构函数私有化。为什么?
因为构造函数私有了,继承了以后创建不了对象,为什么?
因为子类的构造函数必须去调用父类的构造函数,而父类的构造函数私有,子类调用不了。
C++中的继承(一),c++,c++,java,jvm
A的构造函数私有,B是无论如何也调用不了。
A怎么调用呢?A是有办法的。

class A
{
public:
	static A CreateObj()
	{
		return A();
	}
private:
	A()
	{}
};
class B : public A
{};
int main()
{
//要调用函数首先要创建对象
//我们可以用静态成员函数,就可以直接用类去调用它
	A::CreateObj();
	return 0;
}

友元是能不用就不用。

其实C++正常的继承学到这里也差不多了,但是还有一个大坑,我们留到下篇文章文章来源地址https://www.toymoban.com/news/detail-770646.html

到了这里,关于C++中的继承(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++中的继承(二)

    上一篇文章我们C++的正常继承其实已经讲完了,但是后面还有一个大坑。 实际当中继承有单继承和多继承。 单继承就是直接继承一个类。 只有一个直接父类的就叫做单继承。 如果是单继承那就比较简单。 现实世界除了有单继承还有多继承。 多继承就是我一个类我具备另外

    2024年02月04日
    浏览(31)
  • C++ 中的继承和多态

    继承允许我们 依据一个类来定义另一个类 ,这使得创建和维护一个应用程序变得更容易。这样做也达到了重用代码功能和提高执行效率的效果。 派生类的成员可以直接访问基类的保护成员(protected),但不能直接访问基类的私有成员(private) 。不过需要注意的是,派生类

    2024年02月06日
    浏览(42)
  • C++中的继承和派生

    C++ 中的继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承类似,例如儿子继承父亲的财产。 继承(Inheri tan ce) 可以理解为一个类从另一个类获取成员变量和成员函数的过程。例如类 B 继承于类 A,那么 B 就拥有 A 的成员变量和成员函数。 在C++中,

    2024年02月10日
    浏览(40)
  • C++中的继承(超详细)

    继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复

    2024年02月07日
    浏览(30)
  • 【C++进阶之路】第一篇:C++中的继承

    🌟hello,各位读者大大们你们好呀🌟 🍭🍭系列专栏:【C++学习与应用】 ✒️✒️本篇内容:继承的基础概念,定义方法,基类和派生类的转换,继承中类的作用域,什么是隐藏,派生类和默认成员函数,继承和友元,继承与静态函数,菱形继承和虚拟继承,菱形继承总结

    2024年02月02日
    浏览(41)
  • C++中的继承、以及赋值兼容转换。

    一、继承的概念及定义 继承可以使代码复用,允许在保持原有类特性的基础上进行扩展。 举个例子:就好比我现在要封装老师、学生等这些人的属性和方法,但是这些人都有重复的属性和方法,比如name、age、sex等等,那么我可以封装一个人的属性和方法,然后我用老师、学

    2024年02月05日
    浏览(36)
  • Java中的继承

    1.子类继承父类 子类利用“extends\\\"进行继承; 子类通过继承父类从而调用父类中的方法; 子类继承父类之后,必须添加属于自己的新成员变量或者属性,否则继承就没有意义了 2.子类访问父类变量 父类中被public修饰的变量,子类可以直接访问父类成员变量; 父类中被

    2024年02月15日
    浏览(39)
  • C++中菱形继承中的多态在底层是如何实现的。

    如果还不了解菱形继承和多态的底层可以看这两篇文章: C++中多态的底层实现_Qianxueban的博客-CSDN博客 C++的继承以及virtual的底层实现_Qianxueban的博客-CSDN博客

    2024年02月09日
    浏览(40)
  • 【C++庖丁解牛】面向对象的三大特性之一多态 | 抽象类 | 多态的原理 | 单继承和多继承关系中的虚函数表

    🍁你好,我是 RO-BERRY 📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 需要声明的,本节课件中的代码及解释都是在vs2013下的x86程序中,涉及的指针都是4bytes。如果要其他平台

    2024年04月10日
    浏览(57)
  • java中构造函数在继承中的调用顺序是什么?

    在Java中,当创建子类对象时,构造函数的调用顺序遵循以下规则: 父类的静态变量和静态初始化块 :首先,Java会加载父类,并执行父类中的静态变量初始化和静态初始化块(静态代码块)。这只会在类首次被加载到JVM时执行一次。 子类的静态变量和静态初始化块 :接下来

    2024年04月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包