C++中,创建对象后用该对象调用了两次同一个成员函数,最终结果显示的是“12“,请问该成员函数该怎么写?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中,创建对象后用该对象调用了两次同一个成员函数,最终结果显示的是“12“,请问该成员函数该怎么写?相关的知识,希望对你有一定的参考价值。
C++中,创建对象后用该对象调用了两次同一个成员函数,最终结果显示的是“12“,请问该成员函数该怎么写?思路是怎样的呢?
Visual C++简介??虽然微软公司推出了VisualC++.NET(Visual C++7.0),但它的应用的很大的局限性,只适用于Windows2000,Windows XP和Windows NT4.0。所以实际中,更多的是以Visual C++6.0为平台。 Visual C++6.0不仅是一个C++编译器,而且是一个基于Windows操作系统的可视化集成开发环境(integrated development environment,IDE)。Visual C++6.0由许多组件组成,包括编辑器、调试器以及程序向导AppWizard、类向导Class Wizard等开发工具。这些组件通过一个名为Developer Studio的组件集成为和谐的开发环境。 ?
VISUAL C++的安装?
作为visual studio的一个组件,可以通过安装visual studio来获得 VISUAL C++作为一个主流的开发平台一直深受编程爱好者的喜爱,但是很多人却对它的入门感到难于上青天,究其原因主要是大家对他错误的认识造成的,严格的来说VISUAL C++不是门语言,虽然它和C++之间有密切的关系,如果形象点比喻的话,可以把C++看作为一种“工业标准”,而VISUAL C++则是某种操作系统平台下的“厂商标准”,而“厂商标准”是在遵循“工业标准”的前提下扩展而来的。 VISUAL C++应用程序的开发主要有两种模式,一种是WIN API方式,另一种则是MFC方式,传统的WIN API开发方式比较繁琐,而MFC则是对WIN API再次封装,所以MFC相对于WIN API开发更具备效率优势,但为了对WINDOWS开发有一个较为全面细致的认识,笔者在这里还是以讲解WIN API的相关内容为主线。 话说到这里可能更多人关心的是学习VISUAL C++需要具备什么条件,为什么对于这扇门屡攻不破呢? 要想学习好VISUAL C++必须具备良好的C/C++的基础,必要的英语阅读能力也是必不可少的,因为大量的技术文档多以英文形式发布。 VISUAL C++基于C,C++语言,主要由是MFC组成,是与系统联系非常紧密的编程工具,它兼有高级,和低级语言的双重性,功能强大,灵活,执行效率高,几乎可说VISUAL C++在 Windows平台无所不能。最大缺点是开发效率不高。
VISUAL C++适用范围?
1、VISUAL C++主要是针对Windows系统,适合一些系统级的开发,可以方便实现一些底层的调用。在VISUAL C++里边嵌入汇编语言很简单。 2、VISUAL C++主要用在驱动程序开发 3、VISUAL C++执行效率高,当对系统性能要求很高的时候,可用VISUAL C++开发。 4、VISUAL C++主要适用于游戏开发 5、VISUAL C++多用于单片机,工业控制等软件开发,如直接对I/O地址操作,就要用C++。 6、VISUAL C++适用开发高效,短小,轻量级的COM组件,DLL。比如WEB上的控件。 7、VISUAL C++可以开发优秀的基于通信的程序。 8、VISUAL C++可以开发高效灵活的文件操作程序。 9、VISUAL C++可以开发灵活高效的数据库操作程序。 10、VISUAL C++是编CAD软件的唯一选择!!!包括AUTOCAD,UG的二次开发。 11、VISUAL C++在多线程、网络通信、分布应用方面,VISUAL C++有不可比拟的优势。
VISUAL C++技术介绍?
匈牙利命名法规则 一般情况下,变量的取名方式为: 范围前缀_,类型前缀_,限定词。 特殊的类型命名,前缀表示: 类、接口 前缀类型例子备注 Lm Class LmObject 表示类型本身不与范围前缀结合使用 I Interface 接口 IUnknown 注:类名前缀改为Lm,对于非全局的类最好有语义表示其所属模块。类的实例命名与类名大致相同,只是类名语义表示类的通用含义,而类名表示此实例的具体语义。如类名LmSketPoint表示草图点的类定义,而它的两个实例 _StartPoint,_EndPoint分别代表起点和终点的语义。类的实例命名带上前缀_。 特殊约定: a. MouseTool的派生类的前缀为_Mt. b.对话框类的前缀为CDlg. c.橡皮条类的前缀为_Rb. 范围前缀: 前缀类型例子备注 g_ 全局作用域 g_Servers m_ 成员变量m_pDoc, l_ 局部作用域 l_strName 少用 注:编程时尽量少用全程变量,对于全程变量还应在类型前缀后加上如下关键字: 特征模块 : Fea 草图模块 : Sket 装配模块 : Asm 工程图模块: Lay 曲面模块 : Surf 界面模块 : Ui 常用的一般数据类型的前缀 前缀类型内存规格描述例子 ch char 8-bit character chGrade ch TCHAR 16-bit character if _UNICODE is defined chName b BOOL Boolean value bEnabled n int Integer (size dependent on operating system)nLength n UINT Unsigned value (size dependent on operatingsystem) nLength w WORD 16-bit unsigned value wPos l LONG 32-bit signed integer lOffset dw DWORD 32-bit unsigned integer dwRange p * Ambient memorymodel pointer pDoc lp FAR* Far pointer lpDoc lpsz LPSTR 32-bit pointer to character string lpszName lpsz LPCSTR 32-bit pointer to constant character stringlpszName lpsz LPCTSTR 32-bit pointer to constant character stringif _UNICODE is defined lpszName h handle Handle to Windows object hWnd lpfn (*fn)() callbackFar pointer to CALLBACK functionlpfnAbort 常用Windows对象名称缩写 Windows 对象例子变量 MFC类例子对象 HWND hWnd; CWnd* pWnd; HDLG hDlg; CDialog* pDlg; HDC hDC; CDC* pDC; HGDIOBJ hGdiObj; CGdiObject* pGdiObj; HPEN hPen; CPen* pPen; HBRUSH hBrush; CBrush* pBrush; HFONT hFont; CFont* pFont; HBITMAP hBitmap; CBitmap* pBitmap; HPALETTE hPalette; CPalette* pPalette; HRGN hRgn; CRgn* pRgn; HMENU hMenu; CMenu* pMenu; HWND hCtl; CStatic* pStatic; HWND hCtl; CButton* pBtn; HWND hCtl; CEdit* pEdit; HWND hCtl; CListBox* pListBox; HWND hCtl; CComboBox* pComboBox; Visual C++常用宏定义命名列表 前缀符号类型符号例子范围 IDR_ 标识多个资源共享的类型 IDR_MAINFRAME 1to 0x6FFF IDD_ 对话框资源(Dialog)IDD_SPELL_CHECK 1 to 0x6FFF IDB_ 位图资源(Bitmap)IDB_COMPANY_LOGO 1 to 0x6FFF IDC_ 光标资源(Cursor)IDC_PENCIL 1 to 0x6FFF IDI_ 图标资源(Icon) IDI_NOTEPAD1 to 0x6FFF ID_IDM_ 工具栏或菜单栏的命令项 ID_TOOLS_SPELLING0x8000 to 0xDFFF HID_ 命令上下文帮助(Command Helpcontext) HID_TOOLS_SPELLING 0x18000 to 0x1DFFF IDP_ 消息框提示文字资源IDP_INVALID_PARTNO 8 to 0xDFFF HIDP_ 消息框上下文帮助(Message-box Helpcontext) HIDP_INVALID_PARTNO 0x30008 to 0x3DFFF IDS_ 字符串资源(String)IDS_COPYRIGHT 1 to 0x7FFF IDC_ 对话框内的控制资源(Control)IDC_RECALC 8 to 0xDFFF VISUAL C++ 下的数据类型 类型含义 ATOM Atom. For more information, see Atoms. BOOL Boolean variable (should be TRUE or FALSE). BOOLEAN Boolean variable (should be TRUE or FALSE). BYTE Byte (8 bits). CALLBACK Calling convention for callback functions. CHAR 8-bit Windows (ANSI) character. For moreinformation, see Character Sets Used By Fonts. COLORREF Red, green, blue (RGB) color value (32 bits).See COLORREF for information on this type. CONST Variable whose value is to remain constant duringexecution. DWORD 32-bit unsigned integer. DWORD_PTR Unsigned long type for pointer precision. Usewhen casting a pointer to a long type to perform pointer arithmetic. (Alsocommonly used for general 32-bit parameters that have been extended to 64 bitsin 64-bit Windows. ) DWORD32 32-bitunsigned integer. DWORD64 64-bit unsigned integer. FLOAT Floating-point variable. HACCEL Handle to an accelerator table. HANDLE Handle to an object. HBITMAP Handle to a bitmap. HBRUSH Handle to a brush. HCONV Handle to a dynamic data exchange (DDE)conversation. HCONVLIST Handle to a DDE conversation list. HCURSOR Handle to a cursor. HDC Handle to a device context (DC).
VISUAL C++常用技术术语解释?
窗口? 窗口是windows应用程序的基本操作单元,用户通过它与应用程序发生交互,例如输入输出操作等等,从程序的内部工作原来来看,每一个窗口对应一个消息处理队列,应用程序主要通过窗口消息处理函数对用户的输入操作进行响应与处理。要想从程序员的角度充分理解窗口的含义,那么对WNDCLASS这个数据结构进行充分的了解是必须的。
实例?
单个实例代表一个可执行程序在内存中的拷贝,如果一个应用程序执行许多次,那么在内存中就有多少个拷贝,也就可以说明有多少个实例存在。
句柄?
句柄在windows环境下被定义成了一个无符号的整数,用于标识应用程序中不同的对象和同类对象中的不同实例。句柄可以看成是对象的编号,联系上面的实例,那么一个实例句柄就可以看作是单个应用程序在内存中拷贝的唯一身份编号,通常系统只能通过实例句柄去识别不同的应用程序,或者是相同应用程序的不同副本。
资源?
Windows应用程序包含很多资源,例如,菜单,图标,对话框等等,VISUAL C++环境下我们不仅仅可以使用系统下原有的资源,我们也可以定义自己的资源,这些资源被定义在.RC文件中,通过应用程序最后的编译,这些资源文件和程序代码连接在一起,形成一个可执行的.EXE文件或者是一个.DLL的库文件。在使用这些资源的时候,通过WIN API函数学将这些资源调用使用。
窗口消息处理函数?
窗口是人机交互的接口,当窗口接受到输入请求的时候,就会把这一请求交给某一个函数进行处理,而这个函数就是窗口消息处理函数,它能够决定当一个消息被接受到的时候采取什么行动。 消息通常是由一系列的输入操作触发的,比如当我按下鼠标左键那么窗口消息处理函数就会收到一个WM_LBUTTONDOWN的消息信号。在窗口消息处理函数中,我们可以利用switch和case结构进行控制, 针对此消息作出我们想要的操作。
图形设备接口?
应用程序的任何输出操作都需要通过图形设备接口(GDI)中的函数来完成操作,GDI负责系统与用户或绘图程序之间的信息交换,并控制在输出设备上显示图形或者文字,它将程序员与具体的硬件设备隔离开,让程序员不需要考虑硬件设备操作的细节。
回调函数?
回调函数是windows操作系统自己调用的函数,用户是不能直接调用他们的。回调函数的定义必须严格的按照windows标准进行编写。
VISUAL C++中播放声音的方法?
简介?
声音是多媒体的一个重要组成部分,在应用程序中加入声音可以使界面更友好。在VISUAL C++中可以根据不同的应用要求,用不同的方法实现声音的播放。
一.播放声音文件的简单方法?
在VISUAL C++ 中的多媒体动态连接库中提供了一组与音频设备有关的函数。利用这些函数可以方便地播放声音。最简单的播放声音方法就是直接调用VISUAL C++中提供的声音播放函数BOOL sndPlaySound( LPCSTR lpszSound,UINT fuSound ); 或BOOL PlaySound(LPCSTR lpszSound, HMODULE hmod, DWORD fuSound );其中参数lpszSound是需要播放声音的.WAV文件的路径和文件名, hmod在这里为NULL,fuSound是播放声音的标志,详细说明请参考VISUAL C++中的帮助。例如播放C:soundmusic.wav可以用sndPlaySound ("c:\sound\music.wav",SND_ASYNC);或PlaySound("c:\sound\music.wav",NULL, SND_ASYNC|SND_NODEFAULT );如果没有找到music.wav文件,第一种格式将播放系统默认的声音,第二种格式不会播放系统默认的声音。
?
二.将声音文件加入到程序中?
在VISUAL C++的程序设计中,可以利用各种标准的资源,如位图,菜单,对话框等。同时VISUAL C++也允许用户自定义资源,因此我们可以将声音文件作为用户自定义资源加入程序资源文件中,经过编译连接生成EXE文件,实现无.WAV文件的声音播放。 要实现作为资源的声音文件的播放,首先要在资源管理器中加入待播放的声音文件(实现过程并不复杂,这里不在叙述)。假设生成的声音文件资源标识符为IDR_WAVE1。在播放时只需要调用下面的语句: PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(), SND_ASYNC|SND_RESOURCE|SND_NODEFAULT|SND_LOOP); 其中MAKEINTRESOURCE()宏将整数资源标识符转变为字符串,AfxGetResourceHandle()函数返回包含资源的模块句柄, SND_RESOURCE是必须的标志。 作为资源的声音文件的第二种播放方法是把资源读入内存后作为内存数据播放。具体步骤入下: 1.获得包含资源的模块句柄: HMODULE hmod=AfxGetResourceHandle(); 2.检索资源块信息: HRSRChSndResource=FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE1),_T("WAVE")); 3. 装载资源数据并加锁: HGLOBAL hGlobalMem=LoadResource(hmod,hSndResource); LPCTSTRlpMemSound=(LPCSTR)LockResource(hGlobalMem); 4.播放声音文件: sndPlaySound(lpMemSound,SND_MEMORY)); 5.释放资源句柄: FreeResource(hGlobalMem);
三.播放声音文件的高级方法
在VISUAL C++中提供了一组对音频设备及多媒体文件直接进行操作的函数。利用这些函数可以灵活地对声音文件进行各种处理。 首先介绍几个要用到的数据结构。WAVEFORMATEX结构定义了WAVE音频数据文件的格式。WAVEHDR结构定义了波形音频缓冲区。读出的数据首先要填充此缓冲区才能送音频设备播放。WAVEOUTCAPS结构描述了音频设备的性能。MMCKINFO结构包含了RIFF文件中一个块的信息。详细的说明请参考VISUAL C++中的帮助。 下面给出程序流程简图及程序源代码清单,在VISUAL C++环境下可直接使用: 源程序清单如下: LPSTR szFileName;//声音文件名 MMCKINFO mmckinfoParent; MMCKINFO mmckinfoSubChunk; DWORD dwFmtSize; HMMIO m_hmmio;//音频文件句柄 DWORD m_WaveLong; HPSTR lpData;//音频数据 HANDLE m_hData; HANDLE m_hFormat; WAVEFORMATEX * lpFormat; DWORD m_dwDataOffset; DWORD m_dwDataSize; WAVEHDR pWaveOutHdr; WAVEOUTCAPS pwoc; HWAVEOUT hWaveOut; //打开波形文件 if(!(m_hmmio=mmioOpen(szFileName,NULL,MMIO_READ|MMIO_ALLOCBUF))) //File open Error Error("Failed to open the file.");//错误处理函数 return false; //检查打开文件是否是声音文件 mmckinfoParent.fccType=mmioFOURCC(’W’,’A’,’V’,’E’); if(mmioDescend(m_hmmio,(LPMMCKINFO)&mmckinfoParent,NULL,MMIO_FINDRIFF)) //NOT WAVE FILE AND QUIT //寻找 ’fmt’ 块 mmckinfoSubChunk.ckid =mmioFOURCC(’f’,’m’,’t’,’ ’); if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK)) //Can’t find ’fmt’ chunk //获得 ’fmt ’块的大小,申请内存 dwFmtSize=mmckinfoSubChunk.cksize ; m_hFormat=LocalAlloc(LMEM_MOVEABLE,LOWORD(dwFmtSize)); if(!m_hFormat) //failed alloc memory lpFormat=(WAVEFORMATEX*)LocalLock(m_hFormat); if(!lpFormat) //failed to lock the memory if((unsignedlong)mmioRead(m_hmmio,(HPSTR)lpFormat,dwFmtSize)!=dwFmtSize) //failed to read format chunk //离开 fmt 块 mmioAscend(m_hmmio,&mmckinfoSubChunk,0); //寻找 ’data’ 块 mmckinfoSubChunk.ckid=mmioFOURCC(’d’,’a’,’t’,’a’); if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK)) //Can’t find’data’ chunk //获得 ’data’块的大小 m_dwDataSize=mmckinfoSubChunk.cksize ; m_dwDataOffset =mmckinfoSubChunk.dwDataOffset ; if(m_dwDataSize==0L) //no data in the ’data’ chunk //为音频数据分配内存 lpData=new char[m_dwDataSize]; if(!lpData) //faile if(mmioseek(m_hmmio,SoundOffset,SEEK_SET)<0) //Failed to read the data chunk m_WaveLong=mmioRead(m_hmmio,lpData,SoundLong); if(m_WaveLong<0) //Failed to read the data chunk //检查音频设备,返回音频输出设备的性能 if(waveOutGetDeVISUAL C++aps(WAVE_MAPPER,&pwoc,sizeof(WAVEOUTCAPS))!=0) //Unable to allocate or lock memory //检查音频输出设备是否能播放指定的音频文件 if(waveOutOpen(&hWaveOut,DevsNum,lpFormat,NULL,NULL,CALLBACK_NULL)!=0) //Failed to OPEN the wave out devices //准备待播放的数据 pWaveOutHdr.lpData =(HPSTR)lpData; pWaveOutHdr.dwBufferLength =m_WaveLong; pWaveOutHdr.dwFlags =0; if(waveOutPrepareHeader(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0) //Failed to prepare the wave data buffer //播放音频数据文件 if(waveOutWrite(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0) //Failed to write the wave data buffer //关闭音频输出设备,释放内存 waveOutReset(hWaveOut); waveOutClose(hWaveOut); LocalUnlock(m_hFormat); LocalFree(m_hFormat); delete [] lpData; 说明:1)以上使用的音频设备和声音文件操作函数的声明包含在mmsystem.h头文件中,因此在程序中必须用#include "mmsystem.h"语句加入头文件。同时在编译时要加入动态连接导入库winmm.lib,具体实现方法是从Developer Studio的Project菜单中选择Settings,然后在Link选项卡上的Object/Library Modules控制中加入winmm.lib。2)在pWaveOutHdr.lpData中指定不同的数据,可以播放音频数据文件中任意指定位置的声音。3) 以上程序均在VISUAL C++6.0中调试通过,在文中省略了对错误及异常情况的处理,在实际应用中必须加入。 ??
四.结论
在VISUAL C++中可以根据应用需要采用不同的方法播放声音文件。简单应用可以直接调用声音播放函数。第二种方法可以把声音作为资源加入可执行文件中。如果在播放之前要对声音数据进行处理,可用第三种方法。
五.Visual C++.NET
随着NET的时代来临,VISUAL C++也如同VB一样,脱胎换骨到VISUAL C++.NET
相关资料?
资料1?
Visual C++ 6.0 简体中文企业版集成SP6完美版 Visual C++ 6.0 英文企业版集成SP6完美版 Visual Studio 6.0 英文企业版集成SP6完美版 钱能 c++程序设计教程第二版高清PDF版 Essential C++ 中文版+英文版 侯捷译 编程点金之Visual C++(电子教程) iso C++程序调试实用手册 PDF版下载 C++面向对象多线程编程 PDF版下载
资料2?
C++高级编程参考手册 C和C++代码精粹 C++沉思录 C++ Primer 第三版 C++ Primer 第四版中文版高清晰 高质量C++编程指南 C++ 编程思想第1卷标准C++导引 C++ 编程思想第2卷实用编程技术 More Effective C++ 简体中文版
资料3?
C++ Templates 中文版+英文版 C++ Coding Standards[Addison Wesley] Absolute C++ 全彩页代码剖析 Accelerated C++ - Practical Programming by Example Inside the C++ Object Model More Exceptional C++ [Addison Wesley] Exceptional C++ [Addison Wesley] Sams出版 C++ Unleashed C++ GUI Programming with QT4
资料4?
VISUAL C++深入详解 孙鑫作品系列高清PDF版下载 Visual C++ 6傻瓜书快速参考 Visual C++ 6.0 编程实例与技巧(PDF中文版) Visual C++ 21天自学教程 跟我学Visual C++ 6 Visual C++ 6 数据库编程 21天自学教程 CHM The C++ Programming Language 第三版 深度探索C++对象模型 Special Edition Using Visual C++ 6 Professional MFC with VISUAL C++ 6
资料5?
Practical C++ Programming Cross-Platform Development in C++ Iterative UML Development Using VISUAL C++ 6 Ace Programmer's Guide Visual C++高级界面特效制作百例 精通GDI+编程 清华大学出版 Borland C++ Builder 6 开发指南 CHM 孙鑫C++视频教程 rmvb格式全20CD完整版 C++视频教程边用边学Visual C++ 6 (ASF格式) 中山大学蔡培兴 C++语言视频教程全51讲精品推荐 C++程序设计视频教程 东南大学何洁月主讲全80讲(上) 48讲 C++程序设计视频教程东南大学何洁月主讲全80讲(下) 32讲词条图册更多图册 参考技术A 应该有很多方法,以下只是其中的一种,用于计算该函数被调用次数
void fun()
static int count = 0;
count++;
cout<<count;
本回答被提问者采纳 参考技术B 静态变量是一种方法,像楼上写的那样
也可以使用全局变量 参考技术C 不明白你题目的意思
为向量中的所有对象动态调用 C++ 类成员
【中文标题】为向量中的所有对象动态调用 C++ 类成员【英文标题】:Dynamically call C++ class members for all objects in a vector 【发布时间】:2015-01-11 20:04:58 【问题描述】:我有一个问题,我正试图用一个非常不明显的解决方案来解决(至少对我而言)。假设我有一个简单的类
class Foo
private:
int x, y, z;
public:
Foo(int x, int y, int z) : x(x), y(y), z(z)
属性 x、y、z 也有公共的 getter 和 setter。
我有一个类封装了一个 Foo 的向量 Item
,它初始化它们并赋予它们默认值等...
现在Store
正在被第三类Processor
修改。基本上我试图实现的行为如下:
Processor
有一个 std::function 向量,其中包含指向 Store
不同成员的指针,例如 ChangeItemSpecs()
或 ChangeItemSourcing()
。它是一个循环遍历并重复调用的列表。
Processor
在函数被调用后检查Store
,如果它们是“好”的变化。例如,如果商店的总价值增加了,或者商店的运营成本降低了。我可能有不同的处理器来分析包含指向 Store
的不同成员的指针的模型,这些成员做不同的事情。或者可能是同样的事情,但只是运行不同的分析。
如果更改不利,Processor
应该“回滚”所做的更改。 这就是我在设计上苦苦挣扎的地方
最初我想以某种方式获取将要更改的项目的指针和索引,并让Processor
复制它们,因为Item
几乎只是比 POD 类高出一步。如果提议的更改不受欢迎,Processor
会将修改后的 Item
替换为原始的 Item
副本。但这非常低效,因为我有一个非常大的数据集。
我的问题归结为:我想要一种通用的方式来存储有关 Item
(或一堆项目)的先前信息,如果 Processor
不喜欢改变。
我想过创建一个名为Change
的对象,其中Store
可以注册处理和回滚更改的成员,然后让Processor
存储Change
对象的数组。更改将有一个名为“proposeChange”和“回滚”更改的成员(是否存在适合“接受更改”的不同范例?)。然后Processor
将简单地循环遍历每个迭代的每个Change
项目并执行其操作。但这并不能真正解决管理回滚信息的问题。只是另一个抽象......
非常感谢任何帮助。我是否错误地处理了这个问题?有不同的看法吗?我该如何设计它?我真的不需要代码,除非它采用了 C++ 的一些深奥特性,或者非常先进——我只需要有关如何设计高效系统的指导。
其他cmets:
性能是关键。每个“商店”中可能有数十万甚至更多Items
。因此,为什么我认为我首先建议的复制方法对性能的影响太大了。
它应该经得起简单的并行化。这意味着在 Model 中存储状态信息可能不是一个好主意(或者是吗?)。我想非常简单地并行化Processor
中的迭代。如果我忽略了某些事情并且这变得非常复杂,那么我们现在可以忘记这一点。
提前致谢!
【问题讨论】:
回滚让我觉得你应该看看en.wikipedia.org/wiki/Memento_pattern 能否详细说明Store
和Item
之间的关系?我可以看到像 “Store 的不同成员,例如 ChangeItemSpecs()
或 ChangeItemSourcing()
” 和 “每个 Store
中可能有数十万甚至更多项目” 但我没有看到任何关于这种关系的明确描述。
一个商店除了包含许多Item
对象的向量之外,还包含它自己的属性。商店也有公共成员,它们会返回有关项目的汇总统计信息,或提供对特定项目或项目的访问。也可以在商店中添加或删除项目。还有什么相关的吗?
【参考方案1】:
我认为您使用 Change
对象记录修改导致的更改的方法是一个很好的方向。
实际上,这是一种非常实用的方法,根据经验,并行喜欢功能。我不认为我完全理解您的模型,但为了简单起见,我们假设我们只有一个项目列表并且可以插入或删除项目。然后归结为两个简单的转换。
fins(L, i, X) — 插入项目 X 在位置 i 进入列表 L fdel(L, i) — 删除位置 i 处的项目列出 L如你所见,fins-1 = fdel反之亦然。
使用composition,我们可以构建任意复杂的更改。另请注意,通常 (f1 ∘ f2)−1 = f2-1 ∘ f1-1 .
因此,一旦您确定了构成模型更改的基本操作并为每个操作定义了逆向操作,就可以将它们组合成一个复杂的更改,并通过以相反的顺序应用逆向操作来回滚。
如果你喜欢设计模式,这就是 Command 模式。转换对象的好处是它们通常非常简单,可以在需要时进行序列化和存储。
如果您想并行尝试多个更改,您甚至可以使用 Decorator 模式更进一步。您无需将更改直接应用于模型,而是创建一个装饰模型,该模型在每次调用接口函数时应用更改。因此,例如,如果您使用在 L 中的位置 i 处插入项目 X 的转换来装饰模型,则装饰器仅存储此信息。然后,如果对第 j 元素的请求,装饰器检查是否 j i,如果是,则简单地转发到现有模型。否则,如果 j > i,它会转发到模型请求元素 j – 1. 最后,如果 j = i,它返回自己的元素X。每个装饰器只需要存储转换,而不是整个模型。您可以将装饰器堆叠在一起以共享相同的更改。如果您发现更改变得更糟,只需处理掉装饰器,没人会注意到。如果您真的喜欢更改,可以将其应用于模型,但在这种情况下,所有其他装饰器都将失效,因此在并发应用程序中不应该经常发生。
【讨论】:
是的,这就是我要找的!谢谢...在实现这一点时,我肯定面临一些技术挑战——但我认为这完全是一个单独的问题。但是,命令模式与我正在尝试做的事情几乎完美匹配。以上是关于C++中,创建对象后用该对象调用了两次同一个成员函数,最终结果显示的是“12“,请问该成员函数该怎么写?的主要内容,如果未能解决你的问题,请参考以下文章
Oracle 序列创建了两次。 ORA-00955: 名称已被现有对象使用