各位好, 小弟在学习第八章时有一些疑问,希望过来人能帮小弟一下第八章是一个画线条,并可以保存文件的程序其中定义了一个类
class CStroke : public CObject
{
....
DECLARE_SERIAL(CStroke)
}
IMPLEMENT_SERIAL(CStroke ,CObject, 1)宏展开后:class CStroke : public CObject
{
....
friend CArchive& AFXAPI opeator>>(CArchive& ar, CStroke* &pOb) ;
}CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
{
pOb = (CStroke*) ar.ReadObject(RUMTIME_CLASS(CStroke));
}以上的文字出现在书中400页(电子书536页)
我看不懂的地方是 CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
在何时调用,书中第386页(电子书518页)void CObList::Serialize(CArchive& ar)
{
CObject::Serialize(ar);
if (ar.IsStoring())
{
...
}
else
{
DWORD nNewCount = ar.ReadCount();
CObject* newData;
while (nNewCount--)
{
ar >> newData; -----|
AddTail(newData); |
} |
|
V
operator>> 被重载(overloading )化_AFX_INLINE CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)
{ pOb = ar.ReadObject(NULL); return ar; }该处调用的是 CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)
不是 CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)我找不出CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)在何处被
调用,看过这本书的过来人能帮我一下吗,帮我解答一下,小弟先谢了还有书中401页(电子书536页)写到
好,你看到了,為什麼只改寫 operator>>,而沒有改寫 operator<<?原因是 WriteObject 並不需要CRuntimeClass 資訊,但 ReadObject 需要,因為在讀完檔案後還要做動態生成看不懂
各位过来人,尤其是看过这本书的人,帮帮我好吗,小弟先谢了
class CStroke : public CObject
{
....
DECLARE_SERIAL(CStroke)
}
IMPLEMENT_SERIAL(CStroke ,CObject, 1)宏展开后:class CStroke : public CObject
{
....
friend CArchive& AFXAPI opeator>>(CArchive& ar, CStroke* &pOb) ;
}CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
{
pOb = (CStroke*) ar.ReadObject(RUMTIME_CLASS(CStroke));
}以上的文字出现在书中400页(电子书536页)
我看不懂的地方是 CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
在何时调用,书中第386页(电子书518页)void CObList::Serialize(CArchive& ar)
{
CObject::Serialize(ar);
if (ar.IsStoring())
{
...
}
else
{
DWORD nNewCount = ar.ReadCount();
CObject* newData;
while (nNewCount--)
{
ar >> newData; -----|
AddTail(newData); |
} |
|
V
operator>> 被重载(overloading )化_AFX_INLINE CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)
{ pOb = ar.ReadObject(NULL); return ar; }该处调用的是 CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)
不是 CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)我找不出CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)在何处被
调用,看过这本书的过来人能帮我一下吗,帮我解答一下,小弟先谢了还有书中401页(电子书536页)写到
好,你看到了,為什麼只改寫 operator>>,而沒有改寫 operator<<?原因是 WriteObject 並不需要CRuntimeClass 資訊,但 ReadObject 需要,因為在讀完檔案後還要做動態生成看不懂
各位过来人,尤其是看过这本书的人,帮帮我好吗,小弟先谢了
CStroke* newData;
while (nNewCount--)
{
ar >> newData;
宏是常用代码的组合,并不是每一行都必须用到
DECLARE_SERIAL(CStroke)该为DECLARE_DYNCREATEIMPLEMENT_SERIAL(CStroke ,CObject, 1)该为IMPLEMENT_DYNCREATE(CStroke,CObject)重新编译后通过,但可执行文件不能读写文件
我想既然不用到CArchive& AFXAPI operator>>(CArchive& ar,CStroke*& pOb)
是否可以象上面那样更改.
还有
_AFX_INLINE CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)
的使用是否同IMPLEMENT_SERIAL(CStroke ,CObject, 1)没什么关系
我认为只要CStroke 派生之 CObject 就可以使用
_AFX_INLINE CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)
了
不是 CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)我找不出CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)在何处被
调用...我想既然不用到CArchive& AFXAPI operator>>(CArchive& ar,CStroke*& pOb)________________________
你忘了CStroke是从CObject派生的了?建议回头看看第二章先
DECLARE_SERIAL(CStroke)该为DECLARE_DYNCREATE(CStroke)IMPLEMENT_SERIAL(CStroke ,CObject, 1)该为IMPLEMENT_DYNCREATE(CStroke,CObject)保证了CStroke派生之CObject,并具有动太生成能力,满足
CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)的调用你的意思是ar >> newData; 应该是使用
CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
而不是
CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)我不是很清楚, newData 是CObject* 类型的,
operator>> 不是虚函数吧?后来我想用单步跟踪一下到底是调用哪个函数,但老是出现汇编代码
,你能帮我单步一下吗,Frame/scribbl/step1(网上)
Dissect/scribbl/step1(书上附带光盘)第二章,要看哪一部分
CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
而不是
CArchive& AFXAPI operator>>(CArchive& ar,CObject*& pOb)____你理解错了,我的意思是,因为CStroke是从CObject派生的,Serialize到CObject::Serialize(CArchive& ar)的时候会调用CStroke::Serialize(CArchive& ar),于是自然就会调用CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)这个重载。至于为什么Serialize到CObject::Serialize(CArchive& ar)的时候会调用CStroke::Serialize(CArchive& ar),就是第二章的内容了。第二章的继承、虚函数与多态部分。
书中((CObject*)pOb->Serialize(*this)
实际调用的是CStroke::Serialize(*this),这个我理解,Serialize是虚函数
CStroke::Serialize(CArchive& ar),于是自然就会调用CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)这个重载。上面的我不理解书中401页(电子书536页)写到
好,你看到了,為什麼只改寫 operator>>,而沒有改寫 operator<<?原因是 WriteObject 並不需要CRuntimeClass 資訊,但 ReadObject 需要,因為在讀完檔案後還要做動態生成
但前面的代码出现过
ar >> newData;
ar << newData; 为什么有IMPLEMENT_SERIAL(CStroke ,CObject, 1)展开时有
CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)
而不实现
CArchive& AFXAPI operator<< (CArchive& ar,CStroke*& pOb)
前面ar << newData 用到是CArchive& AFXAPI operator<<(CArchive& ar,CObject*& pOb)
不是CArchive& AFXAPI operator<<(CArchive& ar,CStroke*& pOb)
那么这个CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb) 又在哪里用到呢
如果不用到DECLARE_DYNCREATE(CStroke),IMPLEMENT_DYNCREATE(CStroke,CObject)就可以满足要求了,但生成可执行文件又不能读写文件。
operator>>到一个指针的话,是创建一个对象再调用创建的CObject派生类的对象的虚函数Serialize,所以要知道具体的类型。
如果对象已经创建,可以直接调用其Serialize函数而不用operator。
CStroke::Serialize调用之前,有IMPLEMENT_SERIAL(CStroke, CObject, 1),IMPLEMENT_SERIAL(CStroke, CObject, 1)展开成为
class CStroke : public CObject
{
....
friend CArchive& AFXAPI opeator>>(CArchive& ar, CStroke* &pOb) ;
}CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
{
pOb = (CStroke*) ar.ReadObject(RUMTIME_CLASS(CStroke));
}
这里已经在CStroke类里重载友元运算符>>调用CStroke::Serialize的时候,在函数里会用到友元运算符>>,自然是调用CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)了。
============================书中401页(电子书536页)写到
好,你看到了,為什麼只改寫 operator>>,而沒有改寫 operator<<?原因是 WriteObject 並不需要CRuntimeClass 資訊,但 ReadObject 需要,因為在讀完檔案後還要做動態生成
但前面的代码出现过
ar >> newData;
ar << newData; 为什么有IMPLEMENT_SERIAL(CStroke ,CObject, 1)展开时有
CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)
而不实现
CArchive& AFXAPI operator<< (CArchive& ar,CStroke*& pOb)
前面ar << newData 用到是CArchive& AFXAPI operator<<(CArchive& ar,CObject*& pOb)
不是CArchive& AFXAPI operator<<(CArchive& ar,CStroke*& pOb)
那么这个CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb) 又在哪里用到呢
如果不用到DECLARE_DYNCREATE(CStroke),IMPLEMENT_DYNCREATE(CStroke,CObject)就可以满足要求了,但生成可执行文件又不能读写文件。
___________________你又理解错了。等下午有空了再给你解释
另外,IMPLEMENT_SERIAL展开之后没有重载<<,也就是说,没有所谓的CArchive& AFXAPI operator<<(CArchive& ar,CStroke*& pOb)这个东西。
而CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)的确是用到的。再回头看看虚函数、多态和动态创建吧。
"宏是常用代码的组合,并不是每一行都必须用到"
有道理
CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)
根本没有调用到
而CArchive& AFXAPI operator>> (CArchive& ar,CObject*& pOb)
到是调用了我查看宏IMPLEMENT_SERIAL
#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) CObject* PASCAL class_name::CreateObject() { return new class_name; } _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, class_name::CreateObject) AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) { pOb = (class_name*) ar.ReadObject(RUNTIME_CLAS(class_name)); return ar; }
以是我复制该宏到我自己的宏IMP_SERIAL
#define IMP_SERIAL(class_name, base_class_name, wSchema) CObject* PASCAL class_name::CreateObject() { return new class_name; } _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, class_name::CreateObject) AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); 并把该宏的内容放在ScribDoc.h 最顶处
在ScribDoc.cpp 文件中把IMPLEMENT_SERIAL(CStroke, CObject, 1)
改成 IMP_SERIAL(CStroke, CObject, 1)
也就是没有了
CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) { pOb = (class_name*) ar.ReadObject(RUNTIME_CLAS(class_name)); return ar; }
的这个宏,编译工程后,文件具有读写文件功能,
也就是说根本没有调用CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)
调用的是CArchive& AFXAPI operator>> (CArchive& ar,CObject*& pOb)
因为我自己的宏IMP_SERIAL(CStroke, CObject, 1)根本就没有
CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)
的实现至于用IMPLEMENT_DYNCREATE(CStroke,CObject)为什么不可以代替IMPLEMENT_SERIAL
是因为IMPLEMENT_DYNCREATE展开后没有
AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name));
而我自己定义的宏IMP_SERIAL有我用的是vc6.0,而书中390页(电子书523页)
_IMPLEMENT_RUNTIMECLASS(....)
{
.....
static AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name));
.....
}
而我的afx.h文件中
#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) CRuntimeClass* PASCAL class_name::_GetBaseClass() { return RUNTIME_CLASS(base_class_name); } AFX_COMDAT AFX_DATADEF CRuntimeClass class_name::class##class_name = { #class_name, sizeof(class class_name), wSchema, pfnNew, &class_name::_GetBaseClass, NULL }; CRuntimeClass* class_name::GetRuntimeClass() const { return RUNTIME_CLASS(class_name); }
所以IMPLEMENT_SERIAL展开后比IMPLEMENT_DYNCREATE展开多了
AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) { pOb = (class_name*) ar.ReadObject(RUNTIME_CLAS(class_name)); return ar; } 所以即使没有用到CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb)
也不能用IMPLEMENT_DYNCREATE代替IMPLEMENT_SERIAL,因为没有AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name));
不知我的理解是否正确,我看书一向很仔细.不知<<深入>>上的_IMPLEMENT_RUNTIMECLASS
是否有错,我用的vc6.0,而书上用的是vc5.0
CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) { pOb = (class_name*) ar.ReadObject(RUNTIME_CLAS(class_name)); return ar; } 这一段去掉,那么程序的确是没有调用CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)了,也说明如果调用CArchive& AFXAPI operator>> (CArchive& ar,CObject*& pOb)的话正好能在这个例子中完成文件保存的工作。但是,并不能说明没去掉它之前它就没有用到啊。Serialize是虚函数,在调用到CObject::Serialize的时候会跳到CStroke::Serialize里去。此时,如果CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)存在,当然是调用CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb),如果CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)不存在,则会折回到CObject中去寻找有没有>>的重载,如果有,则会调用CArchive& AFXAPI operator>> (CArchive& ar,CObject*& pOb)。
调试窗口中
有:
call CreateObject()
没有:
Call operator>>
说明:
如果CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)存在,也不调用CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)不知是否正确
class A
{
public:
virtual void sound(){AfxMessageBox("Test");}
}class B: public A
{
public:
virtual void sound(){AfxMessageBox("Test");}
}如果有
B b;
那么
b.sound();
回弹出一个对话框。而修改B:
class B: public A
{
public:
virtual void sound();
}
再运行
b.sound();
也会弹出对话框。那么你就能说修改以前的B中的virtual void sound(){AfxMessageBox("Test");}没有被调用到吗?
#include <iostream>
using namespace std ;
class A
{
public:
virtual void sound()=0 ;
};class B: public A
{
public:
virtual void sound(){cout<<"test"<<endl;}
};void main()
{
B b ;
b.sound() ;
}
如果没有调用b.sound(),就不会有test ,按你的例子有 test 不一定会调用
但没有test就一定没有调用b.sound(),因为调用了就一定会有test
同样道理Call operator>> 没出现就没有调用
CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) { TRACE0("Call operator>>\n");pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); return ar; }
在CcriblDoc.cpp中IMP_SERIAL(CStroke, CObject, 1)
展开后就有
CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)
{
TRACE0("Call operator>>\n");
pOb = (CStroke*) ar.ReadObject(RUNTIME_CLASS(CStroke)); return ar; }
没有输出 "Call operator"就一定没有调用
CArchive& AFXAPI operator>> (CArchive& ar,CStroke*& pOb)
虽然出现"Call operator"不一定没有调用再者这个问题跟虚函数没有什么关系
operator>> 不是一个虚函数,没有 virtual关健字CObject* newData;
while (nNewCount--)
{
ar >> newData;
AddTail(newData);
} ;
到底>>该调用哪一个>>呢 ,根据参数的类型决定
ar 属于CArchive类型
newData 属于CObject*类型
故调用CArchive& AFXAPI operator>> (CArchive& ar,CObject*& pOb)
operator >>不是虚函数
你多处说到:
CStroke::Serialize(CArchive& ar),于是自然就会调用CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)这个重载。
我十分不理解,"自然会调用" ?? 难到CStroke::Serialize(CArchive& ar)里面出现的代码
要调用CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
要调用operator>> 是出现在CObjectList::Serialize里边的ar>>newData ;
而此处调用的是CArchive& AFXAPI operator>> (CArchive& ar,CObject*& pOb)
根据参数类型确定,operator>> 不是虚函数
程序里边根本就没有调用CArchive& AFXAPI operator>>(CArchive& ar,CStroke* &pOb)
这个函数,调用了就输出"Call operator>>" ,没输出何来调用