新手指南-序列化篇之三

序列化初步之三(翻译)


 http://www.codeproject.com/cpp/serialization_primer3.asp
在前两部分,我们学习了在通常情况下,如何为序列化提供有力的支持。在这一部分,我们将学习序列化任何一种对象时的特殊的规则。这里有四个常用的参考例子。每个例子都由前一个构成。

Ø        序列化一个简单类

Ø        序列化一个派生类

Ø        序列化一个同源的聚集类

Ø        序列化一个异源的聚集类

我们的Searialize()方法将返回以下状态码之一:

l        Success

l        InvalidFormat

l        UnsupportedVersion

l        ReadError

l        WriteError

序列化一个简单类

一个“简单类”的定义是:一个即没有父类,也没有聚集类的对象。序列化一个简单的类需要以下步骤:

1.      序列化对象签名和版本

2.      序列化对象成员(如果有)

在下面的例子中,类Point包含两个int型变量,表示点的坐标。对象的签名和版本定义成静态成员(m_strSignature和m_nVersion),所以每个Point类的实例都共享它们。

int Point::serialize

    (CArchive* pArchive)

  {

    ASSERT (pArchive != NULL);

 

    // Step 1: Serialize signature and version

    int nVersion;

    try {

      if (pArchive->IsStoring()) {

          (*pArchive) << Point::m_strSignature;

          (*pArchive) << Point::m_nVersion;

      } else {

          CString strSignature;

          (*pArchive) >> strSignature;

          if (strSignature != Point::m_strSignature)

             return (Status::InvalidFormat);

          (*pArchive) >> nVersion;

          if (nVersion > Point::m_nVersion;)

             return (Status::UnsupportedVersion);

      }

 

      // Step 2: Serialize members

      if (pArchive->IsStoring()) {

          (*pArchive) << m_nX;

          (*pArchive) << m_nY;

      } else {

          (*pArchive) >> m_nX;

          (*pArchive) >> m_nY;

      }

    }

    catch (CException* pException) {

      // A read/write error occured

      pException->Delete();

      if (pArchive->IsStoring())

        return (Status::WriteError);

      return (Status::ReadError);

    }

 

    // Object was successfully serialized

    return (Status::Success);

  }

序列化一个派生类

派生类是指派生于一个简单类,并且不是一个聚集类的类。序列化一个派生类需要以下步骤:

1.      序列化对象签名和版本

2.      序列化对象的基类<<额外的步骤

3.      序列化对象的成员(如果有)

在下面的例子中,类ColoredPoint从Point类派生,并且增加一个叫做m_nColor的int型变量,表示点的颜色。如同所有序列化的类一样,ColoredPoint类也定义一个静态签名和版本。

int ColoredPoint::serialize

    (CArchive* pArchive)

  {

    ASSERT (pArchive != NULL);

 

    // Step 1: Serialize signature and version

    int nVersion;

    try {

      if (pArchive->IsStoring()) {

          (*pArchive) << ColoredPoint::m_strSignature;

          (*pArchive) << ColoredPoint::m_nVersion;

      } else {

          CString strSignature;

          (*pArchive) >> strSignature;

          if (strSignature != ColoredPoint::m_strSignature)

             return (Status::InvalidFormat);

          (*pArchive) >> nVersion;

          if (nVersion > ColoredPoint::m_nVersion;)

             return (Status::UnsupportedVersion);

      }

 

      // Step 2: Serialize the base class

      int nStatus = Point::serialize (pArchive);

      if (nStatus != Status::Success)

         return (nStatus);

 

      // Step 3: Serialize members

      if (pArchive->IsStoring())

         (*pArchive) << m_nColor;

      else

         (*pArchive) >> m_nColor;

    }

    catch (CException* pException) {

      // A read/write error occured

      pException->Delete();

      if (pArchive->IsStoring())

        return (Status::WriteError);

      return (Status::ReadError);

    }

 

    // Object was successfully serialized

    return (Status::Success);

  }

序列化一个同源的聚集类

同源聚集类常常用来存储数量不定的多个同类型对象。序列化同源聚集类需要以下步骤:

1.      序列化对象签名和版本

2.      序列化对象的基类(如果有)

3.      序列化聚集对象的数量<<额外的步骤

4.      序列化每个聚集对象<<额外的步骤

5.      序列化对象的其它成员(如果有)

在下面的例子中,类ColoredPointList是一个ColoredPoint对象的聚集。为了简单,ColoredPointList类使用CPtrArray来存储对象。如同所有序列化类一样,ColoredPointList类也定义了一个静态签名和版本。以下是ColoredPointList类的示例:

class ColoredPointList

  {

    // Construction/destruction

    public:

      ColoredPointList::ColoredPointList();

      virtual ColoredPointList::~ColoredPointList();

 

    // Attributes

    public:

      static const CString m_strSignature;

      static const int m_nVersion;

 

    // Operations

    public:

      int serialize (CArchive* pArchive);

 

    // Members

    protected:

      CPtrArray m_coloredPoints;

  }

下面是我们如何序列化它:

int ColoredPointList::serialize

    (CArchive* pArchive)

  {

    ASSERT (pArchive != NULL);

    int nStatus = Status::Success;

 

    // Step 1: Serialize signature and version

    int nVersion;

    try {

      if (pArchive->IsStoring()) {

          (*pArchive) << ColoredPointList::m_strSignature;

          (*pArchive) << ColoredPointList::m_nVersion;

      } else {

          CString strSignature;

          (*pArchive) >> strSignature;

          if (strSignature != ColoredPointList::m_strSignature)

             return (Status::InvalidFormat);

          (*pArchive) >> nVersion;

          if (nVersion > ColoredPointList::m_nVersion;)

             return (Status::UnsupportedVersion);

      }

 

      // Step 2: Serialize base class (if any)

      //

      // Nothing to do since ColoredPointList isn't derived from anything.

      // But if it was derived from BaseColoredPointList, we'd do:

      //

      // nStatus = BaseColoredPointList::serialize (pArchive);

      // if (nStatus != Status::Success)

      //    return (nStatus);

 

      // Step 3: Serialize number of items in collection

      int nItems = 0;

      if (pArchive->IsStoring())

         (*pArchive) << m_coloredPoints.GetSize();

      else

         (*pArchive) >> nItems;

 

      // Step 4: Serialize each object in collection

      for (int nObject=0; (nObject < nItems); nObject++) {

 

          // 4a: Point to object being serialized

          ColoredPoint* pColoredPoint = NULL;

          if (pArchive->IsStoring())

             pColoredPoint = (ColoredPoint *) m_coloredPoints.GetAt (nObject);

          else

             pColoredPoint = new ColoredPoint();

          ASSERT (pColoredPoint != NULL);

 

          // 4b: Serialize it

          nStatus = pColoredPoint->serialize (pArchive);

          if (nStatus != Status::Success)

             return (nStatus);

          if (!pArchive->IsStoring())

             m_coloredPoints.Add (pColoredPoint);

      }

 

      // Step 5: Serialize object's other members (if any)

      //

      // Nothing to do since ColoredPointList doesn't have any other

      // members. But if it contained an int (m_nSomeInt) and a Foo

      // object (m_foo), we'd do:

      //

      // if (pArchive->IsStoring())

      //    (*pArchive) << m_nSomeInt;

      // else

      //    (*pArchive) >> m_nColor;

      //

      // nStatus = m_foo::serialize (pArchive);

      // if (nStatus != Status::Success)

      //    return (nStatus);

 

    }

    catch (CException* pException) {

      // A read/write error occured

      pException->Delete();

      if (pArchive->IsStoring())

        return (Status::WriteError);

      return (Status::ReadError);

    }

 

    // Object was successfully serialized

    return (Status::Success);

  }

序列化一个异源聚集类

异源聚集类常常用来存储数量不定的多个不同类型对象。序列化一个异源聚集类需要以下步骤:

1.      序列化对象签名和版本

2.      序列化对象的基类(如果有)

3.      序列化聚集对象的数量

4.      对于每一个聚集对象

a. 序列化对象签名<<额外的步骤

b.序列化对象

5.      序列化对象的其它成员(如果有)

你会注意到在序列化中一个仅有的额外步骤是4(a),在序列化每个对象自身前,将先序列化每个对象的签名。这样以后读取数据就比较方便。当序列化一个同源聚集类时,我们处理同类型的对象(前一个例子中的ColoredPoint)。为了读取一个ColoredPoint类,我们在堆中构造它,并且调用它的Searialize()方法。

ColoredPoint* pColoredPoint = new ColoredPoint();

 nStatus = pColoredPoint->serialize (pArchive);

当我们处理异源聚集类时,在序列化对象之前,我们需要知道我们读取的对象的类型。这个信息来自于对象的签名。由于我们在序列化对象时已经保存了对象的签名,因此读取时我们可以根据对象的类型构造合适的对象。

// Read object signature

  CString strSignature;

  pArchive >> strSignature;

 

  // Construct object of appropriate type

  ISerializable* pObject = NULL;

  if (strSignature == ColoredPoint::m_strSignature)

     pObject = new ColoredPoint();

  else

    if (strSignature == Line::m_strSignature)

       pObject = new Line();

    else

       if (strSignature == Rectangle::m_strSignature)

          pObject = new Rectangle();

       else

          return (Status::InvalidFormat);

  ASSERT (pObject != NULL);

 

  // Read it back in

  nStatus = pObject->serialize (pArchive);

在上面的代码片段中,ColoredPoint,Line和Rectangle都是(最终)派生于一个公共的基类ISerializable。这个类除了纯虚函数外没有比一个抽象基类更多的内容(换句话说,是一个“接口” )。ISerializable定义方法getSignature(),getVersion和Serialize()。

class ISerializable

  {

    // Construction/destruction

    public:

      ISerializable::ISerializable()

        { }

      virtual ISerializable::~ISerializable()

        { }

 

    // Operations

    public:

      // Get the object's signature

      virtual CString getSignature() = 0;

 

      // Get the object's version

      virtual int getVersion() = 0;

 

      // Serialize the object

      virtual int serialize (CArchive* pArchive) = 0;

  }

好,让我们序列化异源聚集类。在下面的例子中,类ShapeList是可变数量的ColoredPoint,Line和Rectangle对象的聚集,它们都派生于ISerializable。你可以将这些类看做是“ISerializable接口的实现”。

int ShapeList::serialize

    (CArchive* pArchive)

  {

    ASSERT (pArchive != NULL);

    int nStatus = Status::Success;

 

    // Step 1: Serialize signature and version

    int nVersion;

    try {

      if (pArchive->IsStoring()) {

          (*pArchive) << ShapeList::m_strSignature;

          (*pArchive) << ShapeList::m_nVersion;

      } else {

          CString strSignature;

          (*pArchive) >> strSignature;

          if (strSignature != ShapeList::m_strSignature)

             return (Status::InvalidFormat);

          (*pArchive) >> nVersion;

          if (nVersion > ShapeList::m_nVersion;)

             return (Status::UnsupportedVersion);

      }

 

      // Step 2: Serialize base class (if any)

      //

      // Nothing to do since ShapeList isn't derived from anything.

      // But if it was derived from BaseShapeList, we'd do:

      //

      // nStatus = BaseShapeList::serialize (pArchive);

      // if (nStatus != Status::Success)

      //    return (nStatus);

 

      // Step 3: Serialize number of items in collection

      int nItems = 0;

      if (pArchive->IsStoring())

         (*pArchive) << m_shapes.GetSize();

      else

         (*pArchive) >> nItems;

 

      // Step 4: Serialize each object in collection

      for (int nObject=0; (nObject < nItems); nObject++) {

 

          // 4a: First serialize object's signature

          CString strSignature;

          if (pArchive->IsStoring())

             (*pArchive) << pObject->getSignature();

          else

             (*pArchive) >> strSignature;

 

          //

          // 4b: Then serialize object

          //

 

          // 4b (1): Point to object being serialized

          ISerializable* pObject = NULL;

          if (pArchive->IsStoring())

             pObject = (ISerializable *) m_shapes.GetAt (nObject);

          else {

             if (strSignature == ColoredPoint::m_strSignature)

                pObject = new ColoredPoint();

             else

               if (strSignature == Line::m_strSignature)

                  pObject = new Line();

               else

                  if (strSignature == Rectangle::m_strSignature)

                     pObject = new Rectangle();

                  else

                     return (Status::InvalidFormat);

          }

          ASSERT (pObject != NULL);

 

          // 4b (2): Serialize it

          nStatus = pObject->serialize (pArchive);

          if (nStatus != Status::Success)

             return (nStatus);

          if (!pArchive->IsStoring())

             m_shapes.Add (pColoredPoint);

      }

 

      // Step 5: Serialize object's other members (if any)

      //

      // Nothing to do since ShapeList doesn't have any other

      // members.  But if it contained an int (m_nSomeInt) and

      // a Foo object (m_foo), we'd do:

      //

      // if (pArchive->IsStoring())

      //    (*pArchive) << m_nSomeInt;

      // else

      //    (*pArchive) >> m_nColor;

      //

      // nStatus = m_foo::serialize (pArchive);

      // if (nStatus != Status::Success)

      //    return (nStatus);

 

    }

    catch (CException* pException) {

      // A read/write error occured

      pException->Delete();

      if (pArchive->IsStoring())

        return (Status::WriteError);

      return (Status::ReadError);

    }

 

    // Object was successfully serialized

    return (Status::Success);

  }

类工厂

你可以用一个基于签名的“类工厂”来提供一个新的对象实例以替换在代码片段中丑陋的if申明。这里有一些关于类工厂的参考文章:

Generic Class Factory by Robert A. T. Káldy
The Factory Method (Creational) Design Pattern by Gopalan Suresh Raj
Abstract Factory Pattern by Mark Grand
虽然文章是复杂多样的,但在这之后的基本思想是一样的。一个类工厂和类没有多大差别,它提供一个适当的指定的静态方法(例如:create()),这个方法提供一个特殊类型的对象。通过工厂的create()方法,你可以隐藏令人厌恶的if申明。稍微整理一下代码:

...

  // Construct object of appropriate type

  ISerializable* pObject = MyClassFactory::create (strSignature);

  ASSERT (pObject != NULL);

  ...

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/happyparrot/archive/2004/12/20/222842.aspx

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
应用背景为变电站电力巡检,基于YOLO v4算法模型对常见电力巡检目标进行检测,并充分利用Ascend310提供的DVPP等硬件支持能力来完成流媒体的传输、处理等任务,并对系统性能做出一定的优化。.zip深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值