Calling virtual functions, persisting view state, and pod type concepts

Source: Internet
Author: User
Tags constructor garbage collection ini

In C + +, derived virtual functions cannot be called from the constructor of a class because the virtual table is not yet fully established. But it seems to be possible in C #, isn't it? Why is there such a difference?

Indeed, there is a difference between C # and C + + in this area. In C + +, if you call a virtual function from a constructor or destructor, the virtual function that the compiler calls is defined in the class instance that is being constructed (for example, if you call Base::somevirtfn from Base::base), not the lowest-derived instance (the Most derived instance), as you said, because the virtual table is not fully initialized until the lowest-derived constructor is executed. Another argument is that the derived class has not yet been created.

Figure 2 virtual function testsimilarly

When you call a virtual function from a destructor, C + + invokes the destructor of the base class, because the derived class has been destroyed (its destructor has already been invoked). Although this behavior can lead to unexpected results (that is, why calling virtual functions from constructors or destructors is considered a bad programming practice), it is the basic knowledge that most C + + programmers must understand.

As you can point out, it is different in C #. Managed objects-whether in C #, managed C + +, or any other. NET-compatible language-are created as their final type, that is, if you call a virtual function from a constructor or destructor, the system calls the last-layer derived function. The program shown in Figure 1 illustrates this point. If you compile and run this program, you will see the output shown in Figure 2.

This behavior seems strange to C + + programmers. It means that you can call a virtual function of a derived type before the derived class is initialized-that is, before its constructor runs. Similarly, if you call a virtual function from a base class destructor, the function is run after the derived class is destroyed-that is, after the destructor is called. So let's not say the reason for this difference is that it's not just that calling virtual functions from constructors/destructors is considered a bad practice.

Why do Microsoft's guys want to design C # like this? Because it simplifies memory management. In order to free memory, the garbage collector needs to know how large the object is. If C # constructs objects like C + +, you might encounter a situation where there are two objects, Obj1 and Obj2, and the following two statements are true:

typeof (Obj1) ==typeof (OBJ2)
sizeof (OBJ1)!= sizeof (OBJ2)
Because one of the objects is partially constructed. (Don't forget that the garbage collector is running asynchronously.) By constructing the object as a final type, the garbage collector can determine the size of the object from its type. If C # is partially constructed like C + +, the garbage collector will need more code to determine the true size of the partially constructed object. This will lead to complexity and performance degradation, which is daunting to begin with, so Microsoft's guys have decided to implement C # like the one above for faster garbage collection benefits. For this discussion, see Raymond Chen's blog: "The old New Thing."

In the 20,043 month column, you showed how to change the latest view state settings for the File Open dialog box, but it doesn't involve saving the most recent view settings used by this user. The problem I've encountered is to read the Open File dialog box settings that the user already has. I only find a way to read the list box information directly, but when the user chooses the thumbnail mode, that does not get the correct information. Do you have a solution to this?

I'm using the public CFileDialog class to do development, it shouldn't be hard, but it doesn't seem that way. I want to force the view mode of the File Open dialog box to be a thumbnail. I'm going to do it in Visual C + +, can you give me some advice?

Several readers are asking about the thumbnail problem in the File Open dialog box. In my March column, I demonstrated that if you send a WM_COMMAND message to the Shelldll_defview Private window in the File Open dialog box to set a different view mode-but how do you know what the current pattern is? You must get the list control and call Clistctrl::getview:

In dialog class
HWND HLC =:: FindWindowEx (M_hwnd,
NULL, _t ("SysListView32"), null);
clistctrl* plc = (clistctrl*) cwnd::fromhandle (HLC);
DWORD Dwview = Plc->getview ();
Clistctrl::getview returns one of the lv_xxx codes, but as Maarten found, Windows returns Lv_view_icon to both icon mode and thumbnail mode.

So how do you tell which view mode it is? I racked my brains and drilled into the header file to find a message called lvm_getitemspacing, and what was the message for--to get the icon interval. As the name suggests, the icon interval is the pixel interval between icons in the icon view mode. Lvm_getitemspacing is not very good to use, so that MFC did not wrap it (for example, MFC does not clistctrl::geticonspacing such a function). So in MFC you have to send the message yourself:

CSize sz = csize (Plc->sendmessage (lvm_getitemspacing));
Windows returns dimensions in the usual way, cx/cy encoded in high and low letters, and csize decodes you politely. Once you have the icon interval, you can compare it to the system interval value returned by GetSystemMetrics (sm_cxiconspacing). If the icon interval of the list view is the same as the system, the view is icon mode. If it is greater than the system interval, the view is thumbnail mode:

if (Sz.cx > GetSystemMetrics (sm_cxiconspacing)) {
Thumbnail view
} else {
Icon View
}
With so many thumbnails, the next question is how to persist the view state of different user sessions? In this case, when the program terminates, you need to use the profile function to save the last-used pattern in the user's configuration file and restore it again the next time the program is started. I wrote a small demonstration program, Dlgtest. The program uses a class Cpersistopendlg that implements the persistence of the program behavior. This class also uses another class Clistviewshellwnd to encapsulate the Shelldll_defview window (see March column). Clistviewshellwnd contains functions to get and set view modes that differentiate between icons and thumbnail patterns:

Clistviewshellwnd M_WNDLVSW;
...
M_wndlvsw.setviewmode (Odm_view_thumbs);
The Clistviewshellwnd OnDestroy processor saves the view mode in a data member M_lastviewmode. When the dialog box is destroyed, Cpersistopendlg's destructor call Writeprofileint writes this value to the user profile. When the dialog box starts, Cpersistopendlg sends itself an initialization message that calls Getprofileint to read from disk the values stored in the configuration file and set the view mode. PostMessage must be invoked because regular initialization messages wm_initdialog and Cdn_initdone come before the file dialog is fully initialized-for an explanation of this, see the March column.

By the way, you should use GETPROFILEXXX and writeprofilexxx to continue the application settings at any time. MFC wraps these functions with CWINAPP. If you call the application at startup (typically in the InitInstance function) Cmyapp::setregistrykey ("KeyName"), MFC uses the registry to store user configuration information instead of the INI file. The following is the INI file for dlgtest:

[Settings]
viewmode=28717
Occasionally, you see the term "POD type" in some text and C + + documents and in the Microsoft. NET Framework. What does this term mean?

You can think of pod type as a kind of data type from outer space with green protective layer, pod means "Plain old data" (translator: if must be translated into Chinese, it is called "the" Complete and "" "How about!) This is the meaning of the POD type. The exact definition is fairly rough (see C + + ISO standard), which basically means that the POD type contains raw data that is compatible with C. For example, structs and integers are POD types, but classes with constructors or virtual functions are not. POD types do not have virtual functions, base classes, user-defined constructors, copy constructs, assignment operators, or destructor functions.


To conceptualize POD types, you can copy them by copying their bits. In addition, the POD type can be uninitialized. For example:

struct RECT R; Value undefined
Point *ppoints = new point[100]; Ditto
CString s; Calls ctor ==> not POD
Non-POD types typically need to be initialized, either by invoking the default constructor (provided by the compiler) or by its own written constructor.

In the past, POD was important for people who wrote compilers or C-compliant + + programs. Now, POD comes to. NET's environment. In managed C + +, managed types (both __value and __gc) can contain embedded native POD types. Figure 3 illustrates the example code. A managed Circle class can contain point, but cannot contain cpoint classes. If you try to compile pod.cpp you will report a C3633 error: "Cannot define ' M_center '" as a member of managed ' ' Circle ' ' because of the presence of Def Ault constructor ' Cpoint::cpoint ' on class ' CPoint '. (Translator: Because class CPoint has the default constructor ' Cpoint::cpoint ', you cannot define ' m_center ' as a member of the managed class ' Circle ')

The reason that. NET qualifies embedded local objects only for POD types is that it is safe to copy them without worrying about invoking constructors, initializing virtual tables, or any other mechanism required for non-pod types.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.