继承体系下C++对象模型.md

C++零基础到实战:基于Big C++的完整项目源码与工程实践指南 C++作为一门强大的系统级编程语言,其核心在于将面向对象、模板和泛型编程等抽象概念转化为可执行的软件系统。理解这些概念的原理是基础,而掌握如何组织代码、管理依赖和构建项目则是实现技术价值的关键。在实际开发中,模块化设计和工程化实践决定了代码的可维护性和可扩展性。无论是开发桌面应用、游戏引擎还是高性能服务器,良好的项目结构和构建流程都是必备技能。本文聚焦于通过完整的源码项目,将C++核心概念与STL标准库的应用相结合,提供从理论到实践的桥梁,帮助学习者跨越从看懂教材到写出可运行、可维护代码的鸿沟,特别适合计算 阅读详情

一直对C++继承体系中对象的内存分布和实现原理不甚了解,故花了点时间复习整理了一下,如下:

C++的继承关系可分为如下几种情况:

  • 单一的一般继承(带成员变量,虚函数,虚函数覆盖)
  • 多重继承(带成员变量,虚函数,虚函数覆盖)
  • 菱形继承(带成员变量,虚函数,虚函数覆盖)
  • 菱形虚拟继承(带成员变量,虚函数,虚函数覆盖)

下面分别来讨论:

单一的一般继承

这个没什么好说的,基类中有虚函数,所以编译器为其产生了虚表指针,该指针指向一个虚函数表,该虚函数表以NULL结尾(windows下)。子类继承父类,如果符合虚函数覆盖的条件(重载,覆盖与隐藏的区别见这里 ) ,就会覆盖父类的虚函数,由此产生了多态。如果子类新增了一些虚函数,就会添加在子类对象中父类部分的虚函数表的尾部。

代码和对应的内存分布图如下:

//case 1:单一的一般继承(带成员变量,虚函数,虚函数覆盖)
class parent
{
public:
    virtual void f(void)
    {
        cout << "parent::f()" << endl;
    }
    virtual void g()
    {
        cout << "parent::g()" << endl;
    }
    virtual void h()
    {
        cout << "parent::h()" << endl;
    }
    parent() :pi(10)
    {}
private:
    int pi;
};

class child :public parent
{
public:
    virtual void f()
    {
        cout << "child::f()" << endl;
    }
    virtual void g_child()
    {
        cout << "child::g_child()" << endl;
    }
    virtual void h_child()
    {
        cout << "child::h_child()" << endl;
    }
    child() :ci(100)
    {}
private:
    int ci;
};

class  grandchild :public child
{
public:
    virtual void f()
    {
        cout << "grandchild::f()" << endl;
    }
    virtual void g_child()
    {
        cout << "grandchild::g_child()" << endl;
    }
    virtual void h_grandchild()
    {
        cout << "grandchild::h_grandchild()" << endl;
    }
    grandchild() :gci(1000)
    {}
private:
    int gci;
};
void testcase1()
{
    grandchild gc;
    int **p = (int**)&gc;
    int i = 0;
    typedef void(*fun)(void);
    while (*(*p + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
}

一直对C++继承体系中对象的内存分布和实现原理不甚了解,故花了点时间复习整理了一下,如下:
C++的继承关系可分为如下几种情况:
* 单一的一般继承(带成员变量,虚函数,虚函数覆盖)
* 多重继承(带成员变量,虚函数,虚函数覆盖)
* 菱形继承(带成员变量,虚函数,虚函数覆盖)
* 菱形虚拟继承(带成员变量,虚函数,虚函数覆盖)

下面分别来讨论:

单一的一般继承

这个没什么好说的,基类中有虚函数,所以编译器为其产生了虚表指针,该指针指向一个虚函数表,该虚函数表以NULL结尾(windows下)。子类继承父类,如果符合虚函数覆盖的条件(重载,覆盖与隐藏的区别见这里 ) ,就会覆盖父类的虚函数,由此产生了多态。如果子类新增了一些虚函数,就会添加在子类对象中父类部分的虚函数表的尾部。

代码和对应的内存分布图如下:

//case 1:单一的一般继承(带成员变量,虚函数,虚函数覆盖)
class parent
{
public:
    virtual void f(void)
    {
        cout << "parent::f()" << endl;
    }
    virtual void g()
    {
        cout << "parent::g()" << endl;
    }
    virtual void h()
    {
        cout << "parent::h()" << endl;
    }
    parent() :pi(10)
    {}
private:
    int pi;
};

class child :public parent
{
public:
    virtual void f()
    {
        cout << "child::f()" << endl;
    }
    virtual void g_child()
    {
        cout << "child::g_child()" << endl;
    }
    virtual void h_child()
    {
        cout << "child::h_child()" << endl;
    }
    child() :ci(100)
    {}
private:
    int ci;
};

class  grandchild :public child
{
public:
    virtual void f()
    {
        cout << "grandchild::f()" << endl;
    }
    virtual void g_child()
    {
        cout << "grandchild::g_child()" << endl;
    }
    virtual void h_grandchild()
    {
        cout << "grandchild::h_grandchild()" << endl;
    }
    grandchild() :gci(1000)
    {}
private:
    int gci;
};
void testcase1()
{
    grandchild gc;
    int **p = (int**)&gc;
    int i = 0;
    typedef void(*fun)(void);
    while (*(*p + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
}

这里写图片描述

多重继承

多重继承的实现和单一继承的原理差不多,只不过在多重继承里,子类会覆盖所有父类对应的虚函数,并且子类新增的虚函数只添加到第一个被继承的父类的虚函数表尾部,这样主要是为了效率问题。

代码和内存图如下:

//case 2:多重继承(带成员变量,虚函数,虚函数覆盖)
class base1
{
public:
    virtual void f()
    {
        cout << "base1::f()" << endl;
    }
    virtual void g()
    {
        cout << "base1::g()" << endl;
    }
    virtual void h()
    {
        cout << "base1::h()" << endl;
    }
    base1() :ba1(10)
    {}
private:
    int ba1;

};

class base2
{
public:
    virtual void f()
    {
        cout << "base2::f()" << endl;
    }
    virtual void g()
    {
        cout << "base2::g()" << endl;
    }
    virtual void h()
    {
        cout << "base2::h()" << endl;
    }
    base2() :ba2(100)
    {}
private:
    int ba2;

};
class base3
{
public:
    virtual void f()
    {
        cout << "base3::f()" << endl;
    }
    virtual void g()
    {
        cout << "base3::g()" << endl;
    }
    virtual void h()
    {
        cout << "base3::h()" << endl;
    }
    base3() :ba3(1000)
    {}
private:
    int ba3;

};

class derived : public base1, public base2, public base3
{
public:
    virtual void f()
    {
        cout << "derived::f()" << endl;
    }
    virtual void g_derived()
    {
        cout << "derived::g_derived()" << endl;
    }
    derived() :di(10000)
    {}
private:
    int di;
};

void testcase2()
{
    derived d;
    int** p = (int**)&d;
    int i = 0;
    typedef void(*fun)(void);
    while (*(*p + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
    cout << endl;
    i = 0;
    while (*(*p + 1 + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
    cout << endl;
    i = 0;
    while (*(*p + 2 + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
}

这里写图片描述

菱形继承

有时候在逻辑上需要菱形继承。所谓菱形继承,也就是两个或多个派生自同一个父类的类又派生出一个共同的子类。如下:

class base{};
class A:public base{};
class B:public base{};
class derived:public A,public B{}

但菱形继承有一个问题就是base类的部分在一个derived对象中会存在两份,这样不仅浪费空间,还会导致数据访问的二义性和不一致问题。二义性可以在前面加上对应类的作用域解决,数据不一致问题可以用下面将要讲的虚拟继承解决。

代码和内存图如下:

//case 3:菱形继承(带成员变量,虚函数,虚函数覆盖)
class base
{
public:
    virtual void f()
    {
        cout << "base::f()" << endl;
    }
    virtual void g()
    {
        cout << "base::g()" << endl;
    }
    virtual void h()
    {
        cout << "base::h()" << endl;
    }
    base() :bi(10)
    {}
private:
    int bi;
};

class base1 :public base
{
public:
    virtual void f()
    {
        cout << "base1::f()" << endl;
    }
    virtual void g()
    {
        cout << "base1::g()" << endl;
    }
    virtual void h_base1()
    {
        cout << "base1::h_base1()" << endl;
    }
    base1() :b1i(100)
    {}
private:
    int b1i;
};
class base2 :public base
{
public:
    virtual void f()
    {
        cout << "base2::f()" << endl;
    }
    virtual void g()
    {
        cout << "base2::g()" << endl;
    }
    virtual void h_base2()
    {
        cout << "base2::h_base2()" << endl;
    }
    base2() :b2i(1000)
    {}
private:
    int b2i;
};

class derived :public base1, public base2
{
public:
    virtual void f()
    {
        cout << "derived::f()" << endl;
    }
    virtual void g()
    {
        cout << "derived::g()" << endl;
    }
    virtual void h_derived()
    {
        cout << "derived::h_derived()" << endl;
    }
    derived() :di(10000)
    {}
private:
    int di;
};

void testcase3()
{
    derived d;
    int **p = (int**)&d;
    int i = 0;
    typedef void(*fun)(void);
    while (*(*p + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
    cout << endl;
    i = 0;
    while (*(*p + 1 + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
}

这里写图片描述

菱形虚拟继承

为了解决菱形继承中数据的不一致问题,可以使用虚拟继承来解决。也就是说虚拟继承是专为菱形继承而生的,在单一继承中使用虚拟继承不会有什么作用,反而会增加运行的开销,拖慢程序速度。这也就是我为什么没有列出单一虚拟继承的原因。
以如下代码为例子:

class base{};
class base1{}:public virtual base{};
class base2{}:public virtual base{};
class derived:public base1,public base2{};

在derived对象中,只存在一个base部分的实例,原因如下:
base部分由derived构造且base1和base2对象中各有一个指向刚刚构造出来的base对象的指针。因此可以保证derived对象中只存在一个base的实例。

在虚继承中,中间层派生类的虚函数不会追加到父类的虚函数表后面,而是有自己单独的虚表指针。最底层派生类新增的虚函数会增加到第一个被继承的类的虚函数表的尾部(base类在base1和base2的后面)。

代码和内存图如下:

//case 4:菱形虚拟继承(带成员变量,虚函数,虚函数覆盖)
class base
{
public:
    virtual void f()
    {
        cout << "base::f()" << endl;
    }
    virtual void g()
    {
        cout << "base::g()" << endl;
    }
    virtual void h()
    {
        cout << "base::h()" << endl;
    }
    base(int x) :bi(x)
    {}
private:
    int bi;
};

class base1 :virtual public base
{
public:
    virtual void f()
    {
        cout << "base1::f()" << endl;
    }
    virtual void g()
    {
        cout << "base1::g()" << endl;
    }
    virtual void h_base1()
    {
        cout << "base1::h_base1()" << endl;
    }
    base1() :b1i(100),base(100)
    {}
private:
    int b1i;
};
class base2 :virtual public base
{
public:
    virtual void f()
    {
        cout << "base2::f()" << endl;
    }
    virtual void g()
    {
        cout << "base2::g()" << endl;
    }
    virtual void h_base2()
    {
        cout << "base2::h_base2()" << endl;
    }
    base2() :b2i(1000),base(1000)
    {}
private:
    int b2i;
};

class derived :public base1, public base2
{
public:
    virtual void f()
    {
        cout << "derived::f()" << endl;
    }
    virtual void g()
    {
        cout << "derived::g()" << endl;
    }
    virtual void h_derived()
    {
        cout << "derived::h_derived()" << endl;
    }
    derived() :di(10000),base(10000)
    {}
private:
    int di;
};

void testcase4()
{
    base b(1);
    base1 b1;
    base2 b2;
    derived d;
    int **p = (int**)&d;
    int i = 0;
    typedef void(*fun)(void);
    while (*(*p + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
    cout << endl;
    i = 0;
    while (*(*p + 1 + i) != NULL)
    {
        ((fun)*((*p) + i++))();
    }
}

这里写图片描述

【完】

从TrinityCore源码剖析C++大型游戏服务器架构与工程实践 网络编程与C++高级特性是构建高性能服务端的核心技术基石。其原理在于通过事件驱动、多线程与对象模型,高效处理高并发连接与复杂状态同步,以实现低延迟、高吞吐的通信。这项技术的核心价值在于为大型分布式系统,如MMORPG游戏服务器,提供了可扩展、可维护的工程解决方案。典型的应用场景包括在线游戏、实时通信平台和物联网网关。本文将以著名的开源MMORPG服务器项目TrinityCore为具体案例,深入解析其多进程分离式架构、基于“Diff”机制的游戏循环,以及如何运用现代C++和数据库设计来模拟完整的《魔兽世界》游 阅读详情

相关推荐

宜搭,高级认证实操2,FaaS连接器指导教程

找到FaasEntry.java将如下代码整体替换,注意引包。如图所示在util下新建EDSUtil.java代码如下。回到连接器界面点击右上角测试-->测试。连接器工厂-->新建FaaS连接器。保存-->前往云IDE开发。返回如图所示代码,部署成功。

2301_80286061的博客 3343

探索c++对象模型

c++中多态的实现我们都知道,c++中的多态是在虚函数的基础上实现的,用指向派生类的基类指针调用派生类(或基类)中自己的成员函数。那么,具体是怎么实现的呢?其实它是通过虚函数表来实现的,虚函数表是保存虚函数地址的一张表,若一个类中有虚函数,当程序运行时,编译器通过在虚函数表中查找相应的虚函数的地址来调用该函数。对象的继承有如下几类:1.单一继承2.多重继承3.重复继承(钻石...

weixin_33747129的博客 191

Vue3实战:从零构建ElementPlus后台管理系统全流程

本文详细介绍了从零开始使用Vue3和ElementPlus构建后台管理系统的全流程。内容涵盖环境准备、项目初始化、Vite配置、SCSS样式体系搭建、ElementPlus组件库引入与配置,以及封装可复用的SvgIcon组件进行图标管理,旨在帮助开发者快速搭建现代化、可维护的中后台应用。

weixin_29011239的博客 160

保姆级教程:用SSC Tool 5.13为先楫HPM6E00EVK生成8轴EtherCAT从站代码(含XML配置详解)

本文详细介绍了如何使用SSC Tool 5.13为先楫HPM6E00EVK开发板配置8轴EtherCAT从站,包括XML文件深度配置、代码生成与工程整合、烧录与调试技巧。教程涵盖从环境准备到性能优化的全流程,帮助开发者快速实现符合CIA402标准的8轴控制。

weixin_30352645的博客 257

基于 YOLOv26 的高速抛物识别系统:微小目标检测

本文提出了一种基于YOLOv26的高速抛物识别系统,专注于微小目标检测。系统采用多模块协同架构,包括视频预处理、YOLOv26检测、目标跟踪和抛物行为分析等模块。关键技术包括YOLOv26s模型检测、DeepSORT目标跟踪和边缘计算部署。通过构建包含多种抛物类型的专业数据集,并应用数据增强技术提升模型性能。系统实现了车辆检测、微小抛物目标识别、抛物轨迹分析和风险等级评估等功能,可实时检测高速公路上的抛物行为并触发告警,为交通管理提供智能化解决方案。

一键难忘的博客 633

C++后台实践:古老的CGI与Web开发

本文写给C/C++程序猿,也适合其他对历史感兴趣的程序猿。  谈到web开发,大家首先想到的PHP、JavaEE/JSP、.NET/ASP、Ruby on rails、Python的Django等等。可谓百花齐放,你一般不会想到C++和Web开发有什么关系,但其实动态网页的开发(web开发)可是在动态语言发明之前就存在的了。 在天地初开,混沌未分之时,动态网页语言尚未出世,要实现动态网站依赖的就是CGI。谷歌/百度一下CGI,可能会出现很多名词:CGI脚本、CGI程序、CGI标准等等。其实这些都是站在不同角

果冻虾仁 1万+

SAP-ABAP:SAP的BAPI_GOODSMVT_CREATE 深度解析

BAPI_GOODSMVT_CREATE 深度解析** **功能定位**:SAP 标准接口,支持 **11 种库存移动场景**(收货/发货/转储/生产投料等),是 MM 模块集成核心

baidu_35680696的博客 1826

浅谈c++继承与对象模型

刚刚学习过c++的继承方面的知识,现在和大家分享下学习心得。继承可以实现代码的复用,并且允许程序员进行一定的扩展,大大减少了程序员的工作量。先给大家铺垫一点知识, 关于派生类的权限在继承后与基类权限的关系: 首先进程分为以下几个继承方式: 1、单继承 2、多继承 3、菱形继承 我们先谈谈一种比较简单的继承方式,单继承吧 首先我们写了一个单继承的的代码,那

qq_37947286的博客 376

光学测量仿真软件:Zygo_(5).Zygo的数据处理与分析方法

通过上述综合案例,我们可以看到Zygo中的数据处理与分析方法是如何一步一步应用于实际数据的。从数据导入到预处理,再到滤波、表面分析、缺陷检测和数据可视化,每一步都至关重要,最终确保了数据的准确性和可靠性。处理后的数据还可以导出为多种格式,便于在其他软件中进行进一步的处理或报告。希望这个案例能够帮助您更好地理解和应用Zygo中的数据处理与分析方法。

kkchenjj的博客 947

SE模块理解+SE-Resnet模块pytorch实现

文章目录SE模块理解SE实现注意力机制原因SE-resnet网络pytorch实现定义residual定义SE模块 SE模块理解 SENet是Squeeze-and-Excitation Networks的简称,拿到了ImageNet2017分类比赛冠军,其效果得到了认可,其提出的SE模块思想简单,易于实现,并且很容易可以加载到现有的网络模型框架中。SENet主要是学习了channel之间的相关性,筛选出了针对通道的注意力,稍微增加了一点计算量,但是效果比较好。 SE模块广泛应用于去噪,去雨方向,利用SE模

qq_42754919的博客 2万+

继承基础及各种继承体系下的派生对象模型

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

Q_feifeiyu的博客 425

11、AUTOSAR配置全解析:从运行实体到通信接口

本博客详细解析了在Simulink中使用AUTOSAR字典配置AUTOSAR运行实体(Runnables)、运行实体间变量(IRVs)、参数以及多种通信接口的过程。内容涵盖运行实体及其事件的配置、IRV和参数的属性设置,以及发送-接收接口、模式切换接口、客户端-服务器接口、非易失性数据接口、参数接口和触发接口的详细配置方法。通过这些步骤,开发者可以高效地构建符合AUTOSAR标准的汽车电子软件系统。

e3f4g5的博客 123

C++ 详谈继承体系下的构造函数和析构函数

构造函数和析构函数的执行顺序;虚析构函数的作用.

yuzhaokangcode的博客 748

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C++ 对象深度探索笔记一

C++ 对象深度探索笔记<一> 1.封装的成本 首选,我门来看一下C语言中的结构体,当然也可以看做事一个“封装”,我称为它结构体的封装,其实就是里面包含了很多的元素。 #include<iostream> using namespace std; typedef struct Md { int num; char name[256]; }MD; void MdPri...

Travelerwz的博客 282

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C++之《Effective C++》读书总结(1)

**将 C++ 视为一个语言联邦(C、Object-Oriented C++、Template C++、STL)**,是《Effective C++》中极具洞察力的抽象。这种观点强调:C++ 并非单一范式语言,而是由多个相互重叠、规则各异的子语言共同构成。理解这一点,有助于开发者在不同语境下采用恰当的思维模型,避免因误用某一子语言的规则而引发隐蔽缺陷或性能问题。

梅花香自苦寒来,宝剑锋从磨砺出。 2094

深度学习工具包 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")

PiliPlus 1.1.3.23:多账号切换与字幕导出,一次讲清

PiliPlus 是基于 Flutter 开发的 B 站第三方客户端,覆盖 Android、iOS 与桌面端。1.1.3.23 这轮更新重点解决两个日常痛点:同一台设备管理多个账号,以及把字幕用起来、带走。顺带调整了弱网请求重试和弹幕过滤规则。 [![PiliPlus 首页、动态与媒体库界面](https://raw.gitcode.com/gh_mirrors/pi/PiliPlus/raw/

gitblog_00861的博客 673

从零构建魔兽世界服务器:TrinityCore C++源码解析与实战指南

网络编程与数据库设计是构建高并发在线服务的两大基石。网络编程通过事件驱动、多线程等机制高效处理海量连接,而数据库设计则负责数据的持久化存储与高效查询。这两项技术的结合,为大型多人在线游戏(MMORPG)等复杂分布式系统提供了核心支撑。在工程实践中,开发者常通过研究成熟开源项目来掌握这些技术的实际应用。TrinityCore作为一个用C++编写的《魔兽世界》开源服务端,完美融合了网络编程、数据库设计、游戏逻辑与内存管理等关键技术,是学习C++大型项目架构与MMORPG服务器原理的绝佳范例。通过搭建环境、编译调

weixin_33910759的博客 329

SpaceCadetPinball源代码阅读指南:如何理解这个复杂的C++逆向工程项目

SpaceCadetPinball是一个经典的C++逆向工程项目,它完整地还原了Windows系统自带的3D弹珠台游戏。对于想要学习逆向工程和游戏开发的新手来说,这个项目提供了宝贵的实践机会。本文将带你逐步理解这个复杂项目的源代码结构和核心概念。 ## 项目概述与背景 **SpaceCadetPinball**是对Windows经典游戏《3D Pinball for Windows - Spa

gitblog_00761的博客 665

C++继承中重名函数调用规则:从名字隐藏到虚函数多态

在面向对象编程中,继承是实现代码复用和多态的核心机制。其原理在于派生类可以继承并扩展基类的成员,形成层次化的类结构。然而,当基类与派生类出现同名函数时,C++的名字查找规则会引发名字隐藏现象,即派生类成员会隐藏基类所有同名成员,这可能导致意外的编译错误。虚函数机制通过虚函数表实现动态绑定,解决了运行时多态问题,允许通过基类指针调用派生类重写版本。理解重载、隐藏与重写的区别,掌握静态绑定与动态绑定的触发条件,对于编写正确、高效的C++程序至关重要。本文聚焦C++基类与子类重名函数调用,结合名字隐藏和虚函数表等

weixin_33802505的博客 312

C++挖掘程序本质(第二章C++面向对象-中)李明杰-M了个J 配套教材

1. 内存管理 1.1 类中的成员变量,不需要主动回收 类中的成员变量,随着类的对象销毁,一同销毁 #include <iostream> using namespace std; struct Person { int m_age; //用来作一些初始化的工作 Person() { m_age = 0; cout << "Person::Person()"...

CTRA®王大大技术中心 1050

C++类型转换

C++类型转换 MD建档时间:2/2/2016 6:50:01 PM by Jimbowhy 隐式转换当编译认为转换是不存在数据丢失的情况隐匿类型转换就会发生,比如:int i = 1; double j = i; 这里发生了隐式类型转换就是在 j=i 这里,i的值被转换成双精度保存到变量 j。这里的转换是编译器自行转换的,并不用提示用户。隐式类型转换还会发生在函数参数的传递与返回等情况下。又如,字

673

从零到一:Doxygen如何重塑你的C++代码文档化体验

本文详细介绍了Doxygen如何彻底改变C++代码文档化的流程,通过自动化工具实现文档与代码的实时同步。文章涵盖了Doxygen的核心语法、高级文档技巧以及实战案例,展示了其在提升开发效率和代码可维护性方面的显著优势,特别适合中大型C++项目使用。

aa123的博客 665

VS2019 C++项目属性配置核心指南:编译链接与运行时库配置实战

C++构建过程依赖编译器、链接器与运行时库的协同工作,其行为由Visual Studio的项目属性精确控制。理解配置本质即掌握构建流水线的调度逻辑:从头文件搜索路径、C++标准版本选择,到CRT运行时库(/MD、/MT)匹配、预编译头机制及多配置继承体系,每项设置都直接影响ABI兼容性、链接成功率与跨平台可移植性。尤其在集成OpenCV等第三方库或调试LNK2019等链接错误时,属性配置错误远比代码缺陷更常见。本文聚焦VS2019真实开发高频场景,解析7类关键配置的技术原理与工程取舍,覆盖Debug/Rel

weixin_32187037的博客 238

C++ 对象深度探索

1.封装的成本 首选,我门来看一下C语言中的结构体,当然也可以看做事一个“封装”,我称为它结构体的封装,其实就是里面包含了很多的元素。 #include<iostream> using namespace std; typedef struct Md { int num; char name[256]; }MD; void MdPrint(const MD* md) { p...

Linux高级开发的博客 265

C++面向对象实战:Mac VSCode环境搭建职工管理系统

面向对象编程(OOP)是软件工程的核心范式,其通过封装、继承和多态三大特性,将现实世界实体抽象为类与对象,从而构建出模块化、可复用和易维护的代码结构。理解其原理是掌握现代软件开发的基础,其技术价值在于能够有效管理复杂系统的状态与行为,提升代码的组织性和扩展性。这一思想在各类管理软件、游戏引擎和框架开发中有着广泛应用。本文聚焦于一个经典的C++面向对象实践案例——职工管理系统,详细解析了如何运用类继承体系与STL容器,在Mac平台结合VSCode编辑器,从零搭建一个具备增删改查与数据持久化功能的控制台应用。项

weixin_34268310的博客 340
上一篇: 虚拟存储器
下一篇: lua学习笔记.md
SmartBrave
博客等级 码龄12年 25粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值