调用虚拟函数 持续化视图状态 POD 类型概念

2016-01-29 12:24 7 1 收藏

调用虚拟函数 持续化视图状态 POD 类型概念,调用虚拟函数,持续化视图状态,POD 类型概念

【 tulaoshi.com - C语言心得技巧 】

C++ Q&A 专栏...
调用虚拟函数,持续化视图状态,POD 类型概念

原著:Paul DiLascia
翻译:Northtibet

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)

原代码下载:CQA0411.exe (234KB)
原文出处:MSDN Magazine November 2004 (C++ Q&A) 调用虚拟函数 持续化视图状态 POD 类型概念

在 C++ 中,无法从某个类的构造函数中调用派生的虚拟函数,因为虚表还没有完全建立。但是在C#中好像就可以,是这样吗?为什么会有这种差别呢?
Clifton F. Vaughn 确实如此,在这个方面 C# 与 C++ 是有差别的。在 C++ 中,如果你从构造函数或者析构函数中调用虚拟函数,编译器调用的虚拟函数是定义在这个正在被构造的类实例中的(例如,如果从 Base::Base 中调用 Base::SomeVirtFn ),不是最底层派生的实例(the most derived instance),正像你说的那样,因为在最底层派生的构造函数执行之前,虚表还没有完全被初始化。另一种说法是派生类还没有被创建。


Figure 2 虚拟函数 TestSimilarly

  当你从析构函数中调用虚函数时,C++ 调用该基类的析构函数,因为派生类已经被销毁(其析构已经被调用)。虽然这个行为可导致异常结果(此即为什么从构造函数或析构函数中调用虚函数被认为是糟糕的编程实践的原因),它是大多数 C++ 程序员必须了然于心的基本常识。
  正如你所指出的那样,在 C# 有所不同。托管对象——无论是在 C#,托管 C++ 中,还是任何其它的 .NET 兼容语言中——是作为其最终类型被创建的,也就是说,如果你从构造函数或析构函数中调用虚函数,系统调用的是最末层派生的函数。Figure 1 所示程序举例说明了这一点。如果你编译并运行这个程序,你会看到 Figure 2 所示输出。
  这种行为对于 C++ 程序员来说似乎有些奇特。它意味着在派生类被初始化之前,你可以调用某个派生类型的虚拟函数——也就是说在其构造函数运行之前。同样,如果你从基类析构函数中调用虚函数,该函数是在派生类被销毁之后运行的——也就是说在析构函数被调用之后。那么先不说这种差别存在的原因,刚才不是还说从构造函数/析构函数中调用虚函数被认为是糟糕的实践。
  为什么微软的家伙们要像这样来设计 C# 呢?因为它简化了内存管理。垃圾收集器为了释放内存,它需要知道对象有多大。如果 C# 像 C++ 那样构造对象,那么你可能会碰到这样一种情况:有两个对象,Obj1 和 Obj2,下面这两条语句都为真:

typeof(Obj1)==typeof(Obj2) sizeof(Obj1)!= sizeof(Obj2) 

  因为对象之一是被部分构造。(不要忘了垃圾收集器是异步运行的。)通过将对象构造成最终类型,垃圾收集器能从其类型决定对象的大小。如果 C# 像 C++ 那样进行部分构造,则垃圾收集器将需要更多的代码来决定部分构造对象的真实大小。这样将带来复杂性和性能下降,首先要解决这个问题很让人气馁,所以为了较快的垃圾收集利益,微软的家伙们决定像上面那样来实现 C#。有关这方面的讨论参见 Raymond Chen 的 blog:“The Old New Thing”。


在 2004 三月的专栏中,你展示了如何改变文件打开对话框的最新视图状态设置,但没有涉及到保存这个用户使用的最新视图设置。我遇到的问题是读取用户已有的打开文件对话框设置。我只找到直接读取列表框信息的方法,但当用户选择缩略图模式时,那样做不能得到正确的信息。对此你有没有解决办法?

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)Maarten van Dillen   我正在用公共的 CFileDialog 类做开发,应该不是很难,但事情似乎并不是那样。我想强制文件打开对话框的视图模式为缩略图。我要用 Visual C++ 来做,你能否提供一些建议? Elliot Leonard  

有几个读者都在问文件打开对话框中的缩略图问题。在我三月份的专栏中,我示范了如果向文件打开对话框中的 SHELLDLL_DefView 专用窗口发送 WM_COM

来源:http://www.tulaoshi.com/n/20160129/1485982.html

延伸阅读
标签: autocad教程
    D IE SEL(Direct Interpretively Evaluated String Expression Language)是指“直接解释求值的字符串表达式语言”。使用的DIESEL可以控制Auto CAD 系统变量MODEMACRO的值,也可用来编写菜单宏,但只能用来处理字符串。     DIESEL的宏表达式格式如下:     $(字符...
1、将Int 转为varchar经常用 concat函数,比如concat(8,'0') 得到字符串 '80' 2、将varchar 转为Int 用 cast(a as signed) a为varchar类型的字符串 总结:类型转换和SQL Server一样,就是类型参数有点点不同 : CAST(xxx AS 类型) , CONVERT(xxx,类型) 可用的类型 二进制,同带binary前缀的效果 : BINARY 字符型,可带参数 : CHAR() 日期 : ...
标签: Web开发
Javascript函数类型判断完美解决方案 在判断函数类型时,我们通常使用typeof方法,一般情况下,它会得到我们所预想的效果。但是,有一些细节并不为我们所熟知。John Resig 在分析了这些细节之后,为我们提供了一个完美的解决方案,本文将作详细介绍: 一、传统方法不为人所知的细节 毫无疑问,在判断函数类型时,我们使用的是typeof...
标签: 电脑入门
     据媒体报道,虚拟化及其堂兄弟云计算是目前计算机领域的重要趋势。虽然这些口号是人们轻松的话题,但是,人们还没有很好地理解虚拟化的意义以及虚拟化将如何改变人们的生活。这种情况是真实的,部分原因是因为虚拟化有许多种形式,云计算似乎是难以捉摸的。不管怎样,你已经得到了虚拟化和云计算的好处。当使用Web邮...
内容或简介: /** 调用数据库里的一个函数 一个函数本质上一个返回一个结果的存储过程,这个例子示范了怎么调用有in、out和in/out参数的函数 ***********************************/ CallableStatement cs; try { // 调用一个没有参数的函数; 函数返回 a VARCHAR // 预处理callable语句   cs = connection.prepareCall("{? = ca...

经验教程

431

收藏

88
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部