【c++语言基础】浅析C++继承与派生

【C++】继承和派生 继承、派生、多态 阅读详情

原文地址:

http://blog.youkuaiyun.com/qq_33724710/article/details/51635331

测试环境:

Target: x86_64-Linux-gnu

gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2.1) 


定义

要分析继承,首先当然要知道什么是继承:继承是面向对象程旭设计中使代码可以复用的最重要的手段,它允许程序员在原有类特性的基础上进行扩展,增加功能。这样产生的新类,就叫做派生类(子类)。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。


继承的格式

class 子类名 :继承权限 基类名

比如下面分别定义了两个类:

[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:  
  4.     int pub;  
  5. protected:  
  6.     int pro;  
  7. private:  
  8.     int pri;  
  9. };  
  10.   
  11. class B: public A  
  12. {  
  13. };  
如上我们就说类B继承了类A,类B叫做类A的派生类或者子类,A类叫做B类的基类或者父类。

继承关系&访问限定符

之前学习类的成员访问限定符的时候都知道public, protected, private 这三种访问限定符的作用,public修饰的类成员可以在类外被访问,而protected与private则不可以。这三种访问权限又对应这三种继承关系:

 

继承关系可以影响子类中继承自父类的成员变量的访问权限,还是在上个栗子的基础上,我们定义一个B类对象进行如下操作;

[cpp]  view plain  copy
  1. int main()  
  2. {  
  3.     B b1;  
  4.     b1.pub;  
  5.     b1.pro;  
  6.     b1.pri;  
  7.   
  8.   
  9.     return 0;  
  10. }  
编译则会报错:

               

会提示pro与pri变量访问权限分别为protected和private,我们不能在类外使用它们。类似的,在B中定义这样一个成员函数:

[cpp]  view plain  copy
  1. class B: public A  
  2. {  
  3.     void fun()  
  4.     {  
  5.         cout<<pub;  
  6.         cout<<pro;  
  7.         cout<<pri;  
  8.     }  
  9. };  
会报这样的错:

                

即基类中的私有成员在子类中是不可见的。关于三种继承方式的成员访问权限总结如下表:

              

总结:
1. 基类的 private 成员在派生类中是不能被访问的,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为 protected 。可以看出保护成员限定符是因继承才出现的。
2. public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象。
3. protetced/private继承是一个实现继承,基类的部分成员并非完全成为子类接口的一部分,是 has-a 的关系原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的都是公有继承。
4. 不管是哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见(不能访问)。
5. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
6. 在实际运用中一般使用都是public继承,极少场景下才会使用protetced/private继承


继承关系中构造/析构函数调用顺序

在现有类的基础上添加如下的构造与析构函数:

[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:   
  4.     A()  
  5.     {  
  6.         cout<<"A()"<<endl;  
  7.     }  
  8.   
  9.     ~A()  
  10.     {  
  11.         cout<<"~A()"<<endl;  
  12.     }  
  13.   
  14. public:  
  15.     int pub;      
  16. protected:  
  17.     int pro;  
  18. private:  
  19.     int pri;  
  20. };  
  21.   
  22. class B: public A  
  23. {  
  24. public:  
  25.       
  26.     B()  
  27.     {  
  28.         cout<<"B()"<<endl;  
  29.     }  
  30.   
  31.     ~B()  
  32.     {  
  33.         cout<<"~B()"<<endl;  
  34.     }  
  35. };  
然后,在main函数中定义一个类B的对象:B b; 编译运行,看看输出语句的顺序:

                 

先基类构造,后子类构造;析构的时候先析构子类,后析构基类。依旧和以前一样,先构造的后析构(因为在栈上)。

让我们走进几行代码的反汇编世界:

                

这是程序现在运行到了b的定义语句。=> 所指,是当前运行的汇编语句。可以看到,第三条汇编语句调用了B类的构造函数。咦?怎么跟我们刚刚看到的顺序不太一样!不急,先往下看。直接 ni 运行到第三条汇编,然后用 si 命令跟进去:

                

可以看到,程序在正式进入B类的构造函数之前,先调用了A类的构造函数,照这么来看,可以推测出是编译器自动的在B类的构造数的初始化列表位置调用了A类的构造函数。还是让我们把程序看完:

                     

果然,又进入了类A的构造函数。

                     

从A类构造函数出来后,才正式进入类B构造函数。

                   

出main函数作用域时,先调用了B类的构造函数

                  

在B类构造函数的末尾调用了A类构造函数。整个过程与我们看到的输出信息一致。

如果类B中还有一个成员变量是一个类对象,那么构造与析构调用顺序又是哪样?

[cpp]  view plain  copy
  1. class T  
  2. {  
  3.   
  4. public:  
  5.     T(int i = 1)   
  6.     {  
  7.         cout<<"T()"<<endl;  
  8.     }  
  9.   
  10.     ~T()  
  11.     {  
  12.         cout<<"~T()"<<endl;  
  13.     }  
  14. };  
  15.   
  16. class A  
  17. {  
  18. public:   
  19.     A()  
  20.     {  
  21.         cout<<"A()"<<endl;  
  22.     }  
  23.   
  24.     ~A()  
  25.     {  
  26.         cout<<"~A()"<<endl;  
  27.     }  
  28.   
  29. public:  
  30.     int pub;      
  31. protected:  
  32.     int pro;  
  33. private:  
  34.     int pri;  
  35. };  
  36.   
  37. class B: public A  
  38. {  
  39. public:  
  40.       
  41.     B()  
  42.     {  
  43.         cout<<"B()"<<endl;  
  44.     }  
  45.   
  46.     ~B()  
  47.     {  
  48.         cout<<"~B()"<<endl;  
  49.     }  
  50. public:  
  51.     T t;  
  52. };  
还是刚刚的main函数,在运行一下程序:

                       

很明显,先调用基类构造,然后是成员对象的构造函数,最后是该类自身的构造函数,析构函数顺序则相反。具体的汇编代码就不演示了。总结一下:

【说明】
1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
3、基类定义了带有形参表构造函数,派生类就一定要定义构造函数。


继承体系中的作用域

  1. 基类和派生类是不同的作用域
  2. 同名隐藏:子类和父类中有同名成员时,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基类成员 访问父类成员)
  3. 在实际中在继承体系里面最好不要定义同名的成员

[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:  
  4.     int pub;  
  5. };  
  6.   
  7. class B: public A  
  8. {  
  9. public:  
  10.     int pub;  
  11. };  
  12.   
  13. int main()  
  14. {  
  15.     B b;  
  16.     b.pub = 1;    //访问的是派生类的成员变量,基类同名被隐藏  
  17.     b.A::pub = 2;    //指明作用域,访问基类成员变量  
  18.   
  19.     return 0;  
  20. }  


继承与转换--赋值兼容规则--(前提:public继承)

  1. 子类对象可以赋值给父类对象
  2. 父类对象不能赋值给子类对象
  3. 父类的指针/引用可以指向子类对象
  4. 子类的指针/引用不能指向父类对象(但可以通过强制类型转换完成)

友元与继承

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。

[cpp]  view plain  copy
  1. class Person  
  2. {  
  3.     friend void Display(Person &p , Student&s);  
  4. protected :  
  5.     string _name ;  
  6. };  
  7.   
  8. class Student: public Person  
  9. {  
  10. protected :  
  11.     int _stuNum ;  
  12. };  
  13.   
  14. void Display(Person &p , Student &s)  
  15. {  
  16.     cout<<p._name<<endl;  
  17.     cout<<s._name<<endl;  
  18.     cout<<s._stuNum<<endl; //error  
  19. }  
  20. int main()  
  21. {  
  22.     Person p;  
  23.     Student s;  
  24.     Display (p, s);   
  25.     return 0;  
  26. }  

继承与静态成员

基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。如下:

[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:  
  4.     static int i;   //注意这里只是声明  
  5. };  
  6.   
  7. int A::i = 0;  
  8.   
  9. class B : public A  
  10. {};  
  11.   
  12. int main()  
  13. {  
  14.     A a;  
  15.     B b;  
  16.       
  17.     cout<<"a.i="<<a.i<<" "<<"b.i="<<b.i<<endl;  
  18.     a.i++;  
  19.     b.i++;  
  20.     cout<<"a.i="<<a.i<<" "<<"b.i="<<b.i<<endl;  
  21.   
  22.     return 0;  
  23. }  
输出:

                   


单继承&多继承&菱形继承

【单继承】

一个子类只有一个直接父类时称这个继承关系为单继承。

                                                             

【多继承】

一个子类有两个或以上直接父类时称这个继承关系为多继承。

                                   

【菱形继承】

               

                                                 

例:

[cpp]  view plain  copy
  1. class Person  
  2. {  
  3. public :  
  4.     string _name ; // 姓名  
  5. };  
  6. class Student : public Person  
  7. {  
  8.     protected :  
  9.     int _num ; //学号  
  10. };  
  11. class Teacher : public Person  
  12. {  
  13. protected :  
  14.     int _id ; // 职工编号  
  15. };  
  16. class Assistant : public Student, public Teacher  
  17. {  
  18. protected :  
  19.     string _majorCourse ; // 主修课程  
  20. };  
  21. void Test ()  
  22. {  
  23.     // 显示指定访问哪个父类的成员  
  24.     Assistant a ;  
  25.     a.Student ::_name = "xxx";  
  26.     a.Teacher ::_name = "yyy";  
  27. }  

看一下菱形继承的构造与析构函数调用顺序:(main函数中创建了一个D类对象)

B类和C类继承A类,D类继承B和C类:

[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:   
  4.     A(){cout<<"A()"<<endl;}  
  5.   
  6.     ~A(){cout<<"~A()"<<endl;}  
  7. };  
  8.   
  9. class B: public A  
  10. {  
  11. public:  
  12.       
  13.     B(){cout<<"B()"<<endl;}  
  14.   
  15.     ~B(){cout<<"~B()"<<endl;}  
  16. };  
  17.   
  18. class C : public A  
  19. {  
  20. public:  
  21.     C(){cout<<"C()"<<endl;}  
  22.   
  23.     ~C(){cout<<"~C()"<<endl;}  
  24. };  
  25.   
  26. class D : public B, public C  
  27. {  
  28. public:  
  29.     D(){cout<<"D()"<<endl;}  
  30.       
  31.     ~D(){cout<<"~D()"<<endl;}  
  32. };  

         

对照对象模型来看会很清楚。

虚继承--解决菱形继承的二义性和数据冗余的问题

1. 虚继承解决了在菱形继承体系里面子类对象包含多份父类对象的数据冗余&浪费空间的问题。
2. 虚继承体系看起来好复杂,在实际应用我们通常不会定义如此复杂的继承体系。一般不到万不得已都不要定义菱形结构的虚继承体系结构,因为使用虚继承解决数据冗余问题也带来了性能上的损耗。

                            

实际存放情况:

两个Address处存放的是地址,这个地址所代表的空间存放了由当前Address这个位置到_name的偏移量。具体情况略显繁琐,不便演示,可以查看反汇编。

再看一下上面的类中虚继承的情况下构造与析构函数调用顺序:B类和C类虚继承A类

[cpp]  view plain  copy
  1. class A  
  2. {  
  3. public:   
  4.     A(){cout<<"A()"<<endl;}  
  5.   
  6.     ~A(){cout<<"~A()"<<endl;}  
  7. };  
  8.   
  9. class B: virtual  public A  
  10. {  
  11. public:  
  12.       
  13.     B(){cout<<"B()"<<endl;}  
  14.   
  15.     ~B(){cout<<"~B()"<<endl;}  
  16. };  
  17.   
  18. class C : virtual public A  
  19. {  
  20. public:  
  21.     C(){cout<<"C()"<<endl;}  
  22.   
  23.     ~C(){cout<<"~C()"<<endl;}  
  24. };  
  25.   
  26. class D : public B, public C  
  27. {  
  28. public:  
  29.     D(){cout<<"D()"<<endl;}  
  30.       
  31.     ~D(){cout<<"~D()"<<endl;}  
  32. };  

              

对照着对象模型看,只需要调用一次B类构造函数即可。


C++之继承与派生 文章目录1.类的继承与派生1.1 类的继承1.2 类的派生2.访问控制2.1公有继承2.22.3 1.类的继承与派生 1.1 类的继承 多继承和单继承:一个派生类可以同时有多个基类称为多继承: class Derived:public Base1,private Base2{};一个派生类只有一个直接基类称为单继承: class Derived:public Base1{} 直接基类和间接基类:直接参与派生出某类的基类称为直接基类,基类的基类甚至更高的基类称为间接基类 在类的定义中,除了要指定基类外,还 阅读详情

相关推荐

高等数学第五章---定积分(§5.3定积分的计算方法)

这篇博客详细讲解定积分的计算方法,包括直接法、凑微分法、变量代换法和分部积分法。通过典型例题演示如何运用这些技巧计算定积分,特别强调换元必换限的原则和奇偶函数的简化处理。内容涵盖代数变形、三角代换、分段函数积分等常见题型,并附有详细的解题步骤和常见错误分析。适合微积分学习者系统掌握定积分计算技巧,提升解题效率。文中还包含积分等式证明和变限积分函数求导等进阶内容,帮助读者深入理解定积分的应用。

2302_77045867的博客 4334

C++继承和派生

C++通过类派生(classderivation)的机制来支持继承。被继承的类称为基类或超类(superclass),新产生的类为派生类(derivedclass)或子类(subclass)。基类和派生类的集合称作类继承层次结构(hierarchy)。class派生类名访问限定符基类名{private成员表1;//派生类增加或替代的私有成员public成员表2;//派生类增加或替代的公有成员protected成员表3;private。...

小程的博客 3875

ANSYS HFSS 中的相控天线阵列仿真方法

相控天线阵列系统广泛使用,从国防雷达应用到商业 5G 应用。设计这些天线阵列涉及复杂的数学运算,需要全波仿真。Ansys HFSS 全场 3D 电磁仿真软件可以在合理的时间内以较低的计算成本仿真复杂的相控阵天线系统,同时考虑复杂激励、环境(即附近的天线)和平台对其性能的影响。本博客介绍了可用于有效仿真相控天线阵列的不同方法。以下是不同仿真方法的简要概述,视频链接中提供了完整的演示。ANSYS HFSS 提供 4 种不同的相控天线阵列仿真方法:1) 晶胞-无限阵列。

jkh920184196的博客 4254

C++核心知识(五)—— 继承和派生

当使用虚继承时,虚基类是被共享的,也就是在继承体系中无论被继承多少次,对象内存模型中均只会出现一个虚基类的子对象(这和多继承是完全不同的)。即使共享虚基类,但是必须要有一个类来完成基类的初始化(因为所有的对象都必须被初始化,哪怕是默认的),同时还不能够重复进行初始化,那到底谁应该负责完成初始化呢?C++标准中选择在每一次继承子类中都必须书写初始化语句(因为每一次继承子类可能都会用来定义对象),但是虚基类的初始化是由最后的子类完成,其他的初始化语句都不会调用。

此心光明事上练的博客 3929

Synopsys工具filter命令:从数据筛选到高效IC设计的实战指南

在数字集成电路设计流程中,数据筛选与查询是工程师处理海量网表、时序报告和设计约束的核心需求。其原理在于通过声明式查询语言,直接对设计对象(如单元、网络、路径)的属性进行逻辑判断与模式匹配,从而精准定位目标。这种技术价值在于将工程师从繁琐的过程式脚本循环中解放出来,大幅提升代码可读性与运行效率,直接调用工具内置的高性能查询引擎。在实际应用场景中,它广泛用于物理与时序联合分析、层次化模块操作、动态约束生成以及自动化报告生成。本文聚焦于Synopsys工具链中filter命令的高阶用法,深入解析其表达式语法、正则

weixin_28007513的博客 577

Aitoearn内容营销的最佳开源 AI 代理,创建 · 发布 · 互动 · 副业一站式平台,支持渠道:抖音、小红书(红点)、微信通道、快手、哔哩哔哩、微信公众号、抖音等等

Aitoearn内容营销的最佳开源 AI 代理,创建 · 发布 · 互动 · 副业一站式平台,支持渠道:抖音、小红书(红点)、微信通道、快手、哔哩哔哩、微信公众号、抖音等等

struggle2025的博客 1749

C++继承与派生

浅析c++继承与派生!!!

weixin_51884452的博客 976

STM32 HAL库定时器中断里读编码器速度准吗?聊聊MG310电机的测速与防溢出处理

本文探讨了STM32 HAL库在定时器中断中读取编码器速度的精度问题,特别针对MG310电机的测速与防溢出处理提供了解决方案。通过对比定时中断法和编码器模式的性能,揭示了硬件编码器接口在降低误差和CPU占用率方面的优势,并详细介绍了CubeMX配置技巧和防溢出处理的工程实践。

weixin_28720767的博客 401

浅析C++继承与派生

测试环境: Target: x86_64-linux-gnu gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2.1) 定义 要分析继承,首先当然要知道什么是继承:继承是面向对象程旭设计中使代码可以复用的最重要的手段,它允许程序员在原有类特性的基础上进行扩展,增加功能。这样产生的新类,就叫做派生类(子类)。继承呈现了面向对象程

Fireplusplus的博客 1万+

华为OD机试真题 新系统 2026-04-26 Python&JS 实现【项目模块依赖构建顺序规划】

某公司正在开发一个大型软件系统,系统包含 N 个模块,每个模块之间存在构建依赖关系。例如,模块 A 可能依赖于模块 B,这意味着必须先构建模块 B,才能构建模块 A。 请根据依赖关系,输出所有可能的模块构建顺序(按照构建顺序排列模块名称),要求:

MISAYAONE的博客 405

流媒体之LL-HLS 低延时HLS协议

LL-HLS协议通过扩展了HLS协议,为实时直播场景提供了更丰富的功能,如延迟控制、播放列表增量更新、阻止播放列表重新加载等。同时客户端可以更灵活地控制播放列表的加载和播放,以适应各种场景和需求。LL-HLS在直播中的延时可以控制在3s内, 但是即使这样, 还是不如RTMP, RTSP等协议的实时性。

技术控的笔记 3366

【c++】万字长文,浅析c++继承特性

c++继承 全解易懂

Tom_猫的博客 413

QProgressBar:常用接口、样式表及自定义进度条实现

在Qt开发中,QProgressBar 是一个非常常用的控件,用于显示任务的进度。无论是文件下载、数据处理还是其他耗时操作,QProgressBar 都能直观地展示当前进度。本文将详细介绍QProgressBar 的使用方法,包括常用接口、样式表设置,并额外补充一个自定义进度条的C++实现。

u011186532的专栏 1012

C++继承浅析

C++继承浅析前言1.继承的用法1.1单继承1.2多继承2.继承的优点2.1普通实现2.2 继承实现3.继承方式3.1公有继承3.2保护继承3.3私有继承4.继承中的对象模型5.继承中构造和析构顺序6.继承同名成员处理方式7.继承同名静态成员处理方式8.多继承语法9.菱形继承总结 前言 由于自己也是刚学了继承,写这篇博文的目的就是巩固一下自己对继承这个概念的理解,可能在以后的学习过程中会再次对继承有更深入的解析。 继承是面向对象三大特性之一 有些类与类之间存在特殊的关系,例如下图中: 我们发现,定义这些类

qq_46359697的博客 289

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

onkeydown继承哪个类_浅析C++继承与派生

定义要分析继承,首先当然要知道什么是继承:继承是面向对象程旭设计中使代码可以复用的最重要的手段,它允许程序员在原有类特性的基础上进行扩展,增加功能。这样产生的新类,就叫做派生类(子类)。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承的格式class 子类名 :继承权限 基类名比如下面分别定义了两个类:class A{public:int pub;protected:int...

weixin_39630762的博客 167

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

浅析C++中的继承

文章目录继承简介继承的定义继承的定义格式继承的方式`public`继承:`protected`继承:`protected`继承:总结: 继承简介 &amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;nbsp;&amp;amp;amp;amp;amp;nbsp;&am

Mmmmmmmi 431

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

C ++之继承浅析

最近学习到C++中的的派生类,讲到了一个面向对象的继承,然后看书上的例子就感觉有一些熟悉,因为在C语言求struct的时候就有类似的东西,把一个结构体作为另一个结构体的成员,#include <stdio.h>struct A { int a; int b; };struct B { int c; struct A; };int main() { printf

luoyu2249758976的博客 3559

C++中虚函数与虚继承区别浅析笔记

虚继承和虚函数是完全无相关的两个概念。 虚函数:是在函数声明/定义时,必须加上virtual关键字。作用就是让其派生类能够覆盖此函数,从而实现多态(运行时多态)。 补充:编译时多态性:通过重载函数和运算符重载实现。运行时多态性:通过虚函数和继承实现。 还有一点就是在派生类中,继承基类同名的虚函数后,不管派生类中显示写不写virtual,此函数依然是虚函数。 还有一种纯虚函数。纯虚函数在基类...

qq_40324647的博客 1264

浅析C++之封装、继承、多态

面向对象编程的三个基本特征:封装、继承和多态。 一、封装 1、什么是封装?        封装即隐藏对象的属性和实现细节,仅对外公开接口。在C++中就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。        简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,

海阔天空sky的博客 1153

浅析C++中的is-a和has-a关系(公有继承、包含、私有继承)

派生类和基类之间的特俗关系是基于C++继承的底层模型的。 总所周知,C++具有三种继承:公有继承、私有继承、保护继承。最常见的就是公有继承,它建立一种is-a的关系。 如何理解is-a呢?即派生类对象也是一个基类对象,可以对基类对象执行的任何操作,也可以对派生类对象执行。举个栗子: 有一个水果Fruit类,可以保存水果的重量和热量; 香蕉是一种水果,所以可以从Fruit类派生出Banana类;

一蓑烟雨任平生 也无风雨也无晴 1万+

浅析c++继承方式

继承: 1.概念:面向对象的程序设计扩展了基于对象的程序设计,可以提供类型/子类型的关系。这是通 过一种被称为继承(inheritance) 的机制而获得的。类不再是重新实现共享的特征,而是继承 了其父类的数据成员和成员函数。C++通过一种被称为类派生(class derivation) 的机制来支 持继承。被继承的类为基类(base class ),而新的类为派生类(derived cl

Number_0_0的博客 817

【C++】浅析C++中的继承

目录1. 继承基本概念2. 派生类的默认成员函数3. 继承体系内的作用域4. 继承与转换–赋值兼容规则–public继承5. 友元与继承&继承与静态成员6. 单继承&多继承&菱形继承7. 虚拟继承&菱形虚拟继承(重要)1.继承基本概念1.1 【继承含义】继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新

sofia_m的博客 675

继承对象的构造和析构浅析

C++中的虚函数的内部实现机制到底是怎样的呢?     鉴于涉及到的内容有点多,我将分三篇文章来介绍。     第一篇:对象内存模型浅析,这里我将对对象的内存模型进行简单的实验和总结。     第二篇:继承对象的构造和析构浅析,这里我将对存在继承关系的对象的构造和析构进行简单的实验和总结。     第三篇:虚函数的内部机制浅析,这里我将对虚函数内部的实现机制进行实验总结。     我

946

CPP基础学习

CPP基础学习C++ 学习网址C引入C++C++ 重载 引用 友元抽象封装继承多态模板(STL)C++11特性智能指针 C++ 学习网址 CPP 学习 https://www.cplusplus.com/reference/ C++入门教程 面向对象思想 C引入C++ C++struct继承struct C++ 重载 引用 友元 函数重载 抽象 C++ 抽象 封装 C++封装 继承 多态 模板(STL) STL简单例子 Stack_STL C++11特性 智能指针 C++ 智能指针 s

嵌入式与人工智能 1349
上一篇: 【c++语言基础】C/C++ 取整函数ceil(),floor(),向上取整,向下取整
下一篇: 【c++语言基础】虚函数的概念
我不吃鱼鱼
博客等级 码龄9年 79粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值