Implement your own "command ing table" (below)

Source: Internet
Author: User

In the previous article, we discussed how to design a "command ing table". However, in the previous article, all the functions corresponding to the "Command" in the table are of the same type and all return values are void, void function.

What if we want to execute different types of functions based on different "commands? (The difference here means that the return values of the execution function may be different, and the parameter list may be different .). Okay. Let's start to discuss this question.

This may be a little harder than the previous article, and you can use the perseverance of your programmers. After thinking about it, we can use this method in the program to understand the message ing Table Mechanism of MFC (in fact, it is very similar to the Message ing mechanism of MFC ), you can also expand your own design ideas to improve your design level. Most importantly, using it can bring benefits to your program. OK, let's go!

Xxx. h file

1. First, map is essential to match the "command" and "function", and function pointers are indispensable, while commands are of the cstring type, so we can write these two things in the class.

As follows:

Class cparser
{
...

Public:
Typedef void (cparser: * funcpointer) (void );
Map <cstring, funcpointer> m_cmdmap;
 
...
}

2. Now we want to execute different types of functions. The above function pointer is only one type (the return value is void, and the parameter list is void ).

Therefore, we need to define various types of function pointers here.

In addition, an Enum structure is required to indicate the function types we need. (Because the function pointers are all 4 bytes and can be said to be non-typed, we need to define another type to mark it so that we can determine the choice.) Well, you have a good idea. Hurry up and write it down:

// Pre-declare the code, because the code below is not written in the class, and is written outside the class/Front
Class cparser;

Typedef void (cparser: * funcpointer) (void );

// Define a union structure to hold various function pointers

// Actually, union is used for conversion.
// Because the function pointers are defined in union functions, they are all 4 bytes,
// The conversion can be smoothly implemented using the Union feature.
Union functions Functions
{
Funcpointer PFN;
 
Void (cparser: * pfn_vs) (cstring &); // the return value is void and the parameter is cstring. Note that the pfn_vs name indicates that the return value is void and the parameter is cstring.
Void (cparser: * pfn_vsi) (cstring &, INT); // the return value is void. The parameter is cstring. The Int value must be named.
};

// Define an Enum structure to indicate our function type
Enum func_type
{
Fucn_type_void_string, // function type: Return Value: void, parameter: String
Fucn_type_void_string_int // function type: Return Value: void, parameter: String, int
};

3. Now, I have written down the two key things above. We need to consider how to use map to map commands with function pointers.

Because STL map only has two parameters, I need to customize a structure and put it into the second parameter of map. This structure includes the function pointer, function type, then we can find the struct according to the command, and then call the corresponding function pointer according to the function type in the struct. Well, write it down:

// Define another struct in the outer header of the class
Typedef struct functioninfo
{
Enum func_type functype; // Function Type
Funcpointer PFN; // function pointer

} Funcinfo;

// In the class
Class cparser
{
...

Public:
Map <cstring, funcinfo> m_cmdmap; // map is changed to this format.
 
...
}

All right, the Defined variables and structures are all done. We can go to the CPP file to create a table and try to use commands to call functions.

Xxx. cpp File

1. Create a table first. In the constructor

Cparser: cparser ()
{
Funcinfo fi;

// Pay attention to the function type and function pointer type below

Fi. functype = fucn_type_void_string;
Fi. PFN = (funcpointer) (void (cparser: *) (cstring &) & cparser: methoda;
M_cmdmap ["# A"] = Fi;

Fi. functype = fucn_type_void_string_int;
Fi. PFN = (funcpointer) (void (cparser: *) (cstring &, INT) & cparser: methodb;
M_cmdmap ["# B"] = Fi;
}

Due to the limitations of map, it is difficult to write them into macros. You can write them into functions to simplify them a little. In MFC, different function pointer types are matched for different on_xxx macros, which are not described here.
Write a function to simplify and unify table creation.

Void cparser: setcmdmap (lpctstr strcmd, Enum func_type ft, funcpointer PFn)
{
Funcinfo fi;
Fi. functype = ft;
Fi. PFN = PFN;
M_shortmap [strcmd] = Fi;
}

Then we can simplify table creation:

Cparser: cparser ()
{
Setcmdmap ("# A", fucn_type_void_string, (funcpointer) (void (ctestcmdmapdlg: *) (cstring &) & cparser: methoda ));
Setcmdmap ("# B", fucn_type_void_string_int, (funcpointer) (void (ctest1_mapdlg: *) (cstring &, INT) & cparser: methodb ));
}

2. Find the corresponding function based on the command and execute

Now we can find the corresponding functions in the table according to the command. The Code is as follows, which is similar to the Code in the previous article, that is, the switch-case option is selected for the judgment of multiple function pointer types.

Void cparser: execcmd (cstring & strcmd, cstring & strparam)
{
If (m_cmdmap.find (strcmd )! = M_cmdmap.end ())
{
Enum func_type ft;

// Since the function pointers are defined in union functions, they are all 4 bytes,
// The conversion can be smoothly implemented using the Union feature.
Union functions CFS;

FT = m_shortmap [strcmd]. functype;
CFS. PFN = m_cmdmap [strcmd]. PFN;

Switch (FT)
{
Case fucn_type_void_string:
(This-> * CFs. pfn_vs) (strparam); // use the feature conversion of union
Break;
Case fucn_type_void_string_int:
(This-> * CFs. pfn_vsi) (strparam, 1); // use the feature conversion of union
Break;
Default:
Afxmessagebox ("no function type is defined. ");
Break;
}
}
Else
{
Cstring strfmt;
Strfmt. Format ("the function corresponding to/" % S/"is not found. ", Strcmd );
Afxmessagebox (strfmt );
}
}

3. Write the corresponding function

Void cparser: methoda (cstring & strparam)
{
Afxmessagebox (strparam );
}

Void cparser: methodb (cstring & strparam, int nparam)
{
Cstring strfmt;
Strfmt. Format ("% s, % d", strparam, nparam );
Afxmessagebox (strfmt );
}

4. Write a function to test the table.

Void cparser: onbutton1 ()
{
Execcmd (cstring ("# A"), cstring ("123 "));
Execcmd (cstring ("# B"), cstring ("456 "));
}

After testing in step 1, the results are correct. Here, we have implemented a more advanced "command ing table" to execute different types of functions.

Here, I hope you can understand this design method. I am tired too ......

The above code may be incomplete. I wrote a simple and complete MFC Dialog Box program to demonstrate this design. You can download the code at the following address:

Http://www.cppblog.com/Files/dylgsy/TestCmdMap.rar

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.