哪位高人能帮我解决下列问题!!!!

deby 2001-11-17 10:42:32
一> 小弟买了一本 VISUAL <<C++技术内幕>>(第四版) 随书光盘中的例子在VISUAL C++6.0 中编译通不过 实例程序也不能运行。这是为什么?

二> 我看地好多VC程序的例子发现其中有好多的消息处理器是类的保护成员。根据C++规则 保护成员只的类的成员和友员类才能调用。哪么应用程序框架是如何调用这些消息处理器的?

三> 小弟在书上看到这样一行语句
CMyView::CMyView():m_rectEllipse(0,0,200,200){...}
我搞不清 “:” 在这里是什么意思?
我查了好多C++书也没有找到

四>我在VISUAL C++技术内幕这本书的EX04A这个例子中发现它的视类CEx04aView的构造器是保护成员。哪么程序如何生成这个类的实例??

望各位老虾多多指点!!!!
...全文
228 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
deby 2001-11-22
  • 打赏
  • 举报
回复
感谢:stevenW(无情的雨) 顺便问一声!楼上哪是不是你的原作???
如果是的哪就太好了!!!  

关于<<C++技术内幕>>(第四版)的光盘程序!!由于文件太多和总的空间起过 1M 所以不能马上发到你的邮箱,不过不要急我会尽快想法子发过去的!!!:-)

Make Friend. OK???? 我的QQ 24699636
DoItFreely 2001-11-22
  • 打赏
  • 举报
回复
public继承的东西可以在构造函数*里面*初始化,也可以在构造函数的定义的尾部用:分隔开来初始化,private继承的就必须在构造函数的尾部初始化,protected继承我就不清楚了。不过试一下就行,不行的话VC编译时会告诉你成员不可访问。
deby 2001-11-22
  • 打赏
  • 举报
回复
stevenW 2001-11-21
  • 打赏
  • 举报
回复
hi,伙计,能不能把VISUAL <<C++技术内幕>>(第四版)的光盘程序发到我邮箱里?我刚下了本第四版的,想找到第四版的配套程序!rfc2001@sohu.com
thanx a lot!
stevenW 2001-11-21
  • 打赏
  • 举报
回复
初始化C++类成员和在你的MFC应用中加入位置栏

Paul DiLascia

问题

我的问题是关于初始化C++类成员的。我见过许多这样的代码(包括在你的栏目中也见到过):

CSomeClass::CSomeClass()

{

x=0;

y=1;

}

而在别的什么地方则写成下面的样子:

CSomeClass::CSomeClass() : x(0), y(1)

{

}

我的一些程序员朋友说第二种方法比较好,但他们都不知道为什么是这样。你能告诉我这两种类成员初始化方法的区别吗?

回答

从技术上说,你的程序员朋友是对的,但是在大多数情况下,两者实际上没有区别。有两个原因使得我们选择第二种语法,它被称为成员初始化列表:一个原因是必须的,另一个只是出于效率考虑。

让我们先看一下第一个原因——必要性。设想你有一个类成员,它本身是一个类或者结构,而且只有一个带一个参数的构造函数。

class CMember {

public:

CMember(int x) { ... }

};

因为Cmember有一个显式声明的构造函数,编译器不产生一个缺省构造函数(不带参数),所以没有一个整数就无法创建Cmember的一个实例。

CMember* pm = new CMember; // Error!!

CMember* pm = new CMember(2); // OK

如果Cmember是另一个类的成员,你怎样初始化它呢?你必须使用成员初始化列表。

class CMyClass {

CMember m_member;

public:

CMyClass();

};

//必须使用成员初始化列表

CMyClass::CMyClass() : m_member(2)

{

•••

}

没有其它办法将参数传递给m_member,如果成员是一个常量对象或者引用也是一样。根据C++的规则,常量对象和引用不能被赋值,它们只能被初始化。

第二个原因是出于效率考虑,当成员类具有一个缺省的构造函数和一个赋值操作符时。MFC的Cstring提供了一个完美的例子。假定你有一个类CmyClass具有一个Cstring类型的成员m_str,你想把它初始化为"yada yada."。你有两种选择:

CMyClass::CMyClass() {

// 使用赋值操作符

// CString::operator=(LPCTSTR);

m_str = _T("yada yada");

}

//使用类成员列表

// and constructor CString::CString(LPCTSTR)

CMyClass::CMyClass() : m_str(_T("yada yada"))

{

}

在它们之间有什么不同吗?是的。编译器总是确保所有成员对象在构造函数体执行之前初始化,因此在第一个例子中编译的代码将调用CString::Cstring来初始化m_str,这在控制到达赋值语句前完成。在第二个例子中编译器产生一个对CString:: CString(LPCTSTR)的调用并将"yada yada"传递给这个函数。结果是在第一个例子中调用了两个Cstring函数(构造函数和赋值操作符),而在第二个例子中只调用了一个函数。在Cstring的例子里这是无所谓的,因为缺省构造函数是内联的,Cstring只是在需要时为字符串分配内存(即,当你实际赋值时)。但是,一般而言,重复的函数调用是浪费资源的,尤其是当构造函数和赋值操作符分配内存的时候。在一些大的类里面,你可能拥有一个构造函数和一个赋值操作符都要调用同一个负责分配大量内存空间的Init函数。在这种情况下,你必须使用初始化列表,以避免不要的分配两次内存。在内部类型如ints或者longs或者其它没有构造函数的类型下,在初始化列表和在构造函数体内赋值这两种方法没有性能上的差别。不管用那一种方法,都只会有一次赋值发生。有些程序员说你应该总是用初始化列表以保持良好习惯,但我从没有发现根据需要在这两种方法之间转换有什么困难。在编程风格上,我倾向于在主体中使用赋值,因为有更多的空间用来格式化和添加注释,你可以写出这样的语句:x=y=z=0;

或者memset(this,0,sizeof(this));

注意第二个片断绝对是非面向对象的。

当我考虑初始化列表的问题时,有一个奇怪的特性我应该警告你,它是关于C++初始化类成员的,它们是按照声明的顺序初始化的,而不是按照出现在初始化列表中的顺序。

class CMyClass {

CMyClass(int x, int y);

int m_x;

int m_y;

};

CMyClass::CMyClass(int i) : m_y(i), m_x(m_y)

{

}

你可能以为上面的代码将会首先做m_y=I,然后做m_x=m_y,最后它们有相同的值。但是编译器先初始化m_x,然后是m_y,,因为它们是按这样的顺序声明的。结果是m_x将有一个不可预测的值。我的例子设计来说明这一点,然而这种bug会更加自然的出现。有两种方法避免它,一个是总是按照你希望它们被初始化的顺序声明成员,第二个是,如果你决定使用初始化列表,总是按照它们声明的顺序罗列这些成员。这将有助于消除混淆。

deby 2001-11-21
  • 打赏
  • 举报
回复
iamQQ(蛐蛐) 我也和你彼有同感!!!

--有的成员在构造器的“:”后初始化
--有的成员在构造器{}内初始化或new一个成员

搞不清为什么为这样???这有什么不同?????
iamQQ 2001-11-21
  • 打赏
  • 举报
回复
翻开书看了看:觉得我对问题分析有误。这只是对CMyView中的普通数据成员m_rectEllipse在构造函数中进行初始化。
iamQQ 2001-11-21
  • 打赏
  • 举报
回复
第三个问题:
这是一个对带参数的构造函数进行初始化的过程
CMyView::CMyView():m_rectEllipse(0,0,200,200){...}

上面是初始化表
具体说来,这是对CMyView的父类成员m_rectEllipse进行初始化。另外注意:对构造函数进行初始化分两部分,1原来父类的 2。本类的
deby 2001-11-21
  • 打赏
  • 举报
回复
wanliduxing(光光) 老兄:您说的话实在是太正确,太具有哲理了!!!!我咋就不明白了?
deby 2001-11-20
  • 打赏
  • 举报
回复
xxtliu()老兄
能不能说得祥细一点呀!!!
wanliduxing 2001-11-20
  • 打赏
  • 举报
回复
老兄,还是自己多看看吧。
大部分是靠自己去体会理解的,找些例子看看吧,不是靠问出来的。何况你想在有些基础知识还不太清楚。
xxtliu 2001-11-20
  • 打赏
  • 举报
回复
这不就是一个继承的问题,几乎每一本讲C++的书都会讲的,你肯定是没有注意了
deby 2001-11-20
  • 打赏
  • 举报
回复
顶!
sungang 2001-11-20
  • 打赏
  • 举报
回复
欢迎下载我们的软件
http://www.csdn.net/cnshare/soft/4/4632.html
deby 2001-11-20
  • 打赏
  • 举报
回复
关于哪个是保护成员的消息处理器的问题,我昨晚想好久我吾出了一个道理。。。。->\n

书上的例子没有问题,是我没搞明白!!!!!哎。。。

可我还是不明白

是不是通过<<深入浅出>>MFC一书中所提到的哪个COMMAND ROUTING(命令传递)间接调用这些“是保护成员的消息处理器的” 如果是这样的哪也太悬了吧!!!!
ccmouse 2001-11-19
  • 打赏
  • 举报
回复
不好意思,你没有冒犯,使我没看清楚,没说清楚。
我觉得可能与DoItFreely(Freely)说的那个问题的原因相同。
关于 :就像wavecheng(CryingOwl)说的那样。还可以跟基类:
:Base(0,0..),m_..(0),..{..}
语法在msdn里有的,不过我看不懂。
czh306 2001-11-19
  • 打赏
  • 举报
回复
看看<<effectiveC++>>就明白了CMyView::CMyView():m_rectEllipse(0,0,200,200){...}
这是列表赋值,对基类初始化必须权这样做。
deby 2001-11-19
  • 打赏
  • 举报
回复
ccmouse() 老兄!
你说的--“保护成员可由类的派生成员访问。你说的是private” (引用原文)

在VC程序中自己(指程序的编写者)定义的消息处理器都在最终类里 如MyVeiw MyApp MyDocument MyFrame中 你还能用这些类作为基类吗?
在windows程序中消息处理器一般由窗口函数调用!!

关于哪个“:”
我也能猜到CMyView::CMyView():m_rectEllipse(0,0,200,200){...}的意思!
但我在书上找不到关于“:”这个运数符的定义

以上如有不对请多多指教!!!!!!
多有冒犯请多包函!!!!!
谢谢你的参入!
                   deby 2001.11.19
ccmouse 2001-11-19
  • 打赏
  • 举报
回复
没解决吗,除了第一个以外。
deby 2001-11-19
  • 打赏
  • 举报
回复
有可能是通过CRuntimeCall中的CreatClass来生成类实例的!!!谢谢!!DoItFreely(Freely)  但其它的问题没有得到解决!!!

所以我还顶!!!!!:)
加载更多回复(10)

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧