Ivor Horton’s Beginning Visual C++ 2005 phần 5 pot

122 327 0
Ivor Horton’s Beginning Visual C++ 2005 phần 5 pot

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

definition, your code will not compile. You’ve seen this code already, so I won’t discuss it again. It would be a good idea to save the file at this point by clicking the Save toolbar button. Get into the habit of sav- ing the file you’re editing before you switch to something else. If you need to edit the constructor again, you can get to it easily by either double-clicking its entry in the lower pane on the Class View tab or by selecting it from the right drop-down menu above the pane displaying the code. You can also get to a member function’s definition in a .cpp file or to its declaration in a .h file directly by right-clicking its name in the Class View pane and selecting the appropriate item from the context menu that appears. Adding Function Members You need to add all the functions you saw earlier to the CBox class. Previously, you defined several func- tion members within the class definition, so that these functions were automatically inline. You can achieve the same result by entering the code in the class definition for these functions manually, or you can use the Add Member Function wizard. You might think that you can define each inline function in the .cpp file, and add the keyword inline to the function definitions, but the problem here is that inline functions end up not being “‘real” func- tions. Because the code from the body of each function has to be inserted directly at the position it is called, the definitions of the functions need to be available when the file containing calls to the functions is compiled. If they’re not, you’ll get linker errors and your program will not run. If you want member functions to be inline, you must include the function definitions in the .h file for the class. They can be defined either within the class definition, or immediately following it in the .h file. You should put any global inline functions you need into a .h file and #include that file into any .cpp file that uses them. To add the GetHeight() function as inline, right-click on CBox on the Class View tab and select Add > Add Function from the context menu. You then can enter the data defining the function in the dialog that is displayed, as Figure 8-11 shows. Figure 8-11 448 Chapter 8 11_571974 ch08.qxp 1/20/06 11:21 PM Page 448 You can specify the return type to be double by selecting from the drop-down list, but you could equally well type it in. Obviously, for a type that does not appear in the list, you would just enter it from the keyboard. Selecting the inline checkbox ensures that GetHeight() will be created as an inline function. Note the other options to declare a function as static, virtual, or pure. As you know, a static member function exists independently of any objects of a class. We’ll get to virtual and pure vir- tual functions in Chapter 9. The GetHeight() function has no parameters so nothing further needs to be added. Clicking the OK button will add the function definition to the class definition in Box.h. If you repeat this process for the GetWidth(), GetLength(), and Volume() member functions, the CBox class definition in Box.h will look like this: #pragma once class CBox { public: CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0); ~CBox(void); private: // Length of a box in inches double m_Length; // Width of a box in inches double m_Width; // Height of a box in inches double m_Height; public: double GetHeight(void) { return 0; } double GetWidth(void) { return 0; } double CBox::GetLength(void) { return 0; } // Calculate the volume of a box double Volume(void) { return 0; } }; An additional public section has been added to the class definition that contains the inline function defi- nitions. You need to modify each of the definitions to provide the correct return value and to declare the functions to be const. For example, the code for GetHeight() function should be changed to: double GetHeight(void) const { return m_Height; } 449 More on Classes 11_571974 ch08.qxp 1/20/06 11:21 PM Page 449 You can change the definitions of the GetWidth() and GetLength() functions in a similar way. The Volume() function definition should be changed to: double Volume(void) const { return m_Length*m_Width*m_Height; } You could enter the other non-inline member functions directly in the editor pane that shows the code, but of course you can also use the Add Member Function wizard to do it, and the practice will be useful. Right-click CBox in the Class View tab and select the Add/Add Function menu item from the context menu, as before. You can then enter the details of the first function you want to add in the dialog that appears, as Figure 8-12 shows. Figure 8-12 Here I have defined the operator+() function as public with a return type of CBox. The parameter type and name have also been entered in the appropriate fields. You must click the Add button to register the parameter as being in the parameter list before clicking the Finish button. This also updates the function signature shown at the bottom of the Add Member Function Wizard dialog box. You could then enter details of another parameter if there was more than one and click Add once again to add it. I have also entered a comment in the dialog box and the wizard will insert this in both Box.h and Box.cpp. When you click on Finish, the declaration for the function is added to the class definition in the Box.h file, and a skeleton definition for the function is added to the Box.cpp file. The function needs to be declared as const so you must add this keyword to the declaration of the operator+() function within the class definition, and to the definition of the function on Box.cpp. You must also add the code in the body of the function, like this: 450 Chapter 8 11_571974 ch08.qxp 1/20/06 11:21 PM Page 450 CBox CBox::operator +(const CBox& aBox) const { // New object has larger length and width of the two, // and sum of the two heights return CBox(m_Length > aBox.m_Length ? m_Length : aBox.m_Length, m_Width > aBox.m_Width ? m_Width : aBox.m_Width, m_Height + aBox.m_Height); } You need to repeat this process for the operator*() and operator/() functions that you saw earlier. When you have completed this, the class definition in Box.h looks something like this: #pragma once class CBox { public: CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0); ~CBox(void); private: // Length of a box in inches double m_Length; // Width of a box in inches double m_Width; // Height of a box in inches double m_Height; public: double GetHeight(void) const { return m_Height; } public: double GetWidth(void) const { return m_Width; } public: double GetLength(void) const { return m_Length; } public: double Volume(void) const { return m_Length*m_Width*m_Height; } 451 More on Classes 11_571974 ch08.qxp 1/20/06 11:21 PM Page 451 public: // Overloaded addition operator CBox operator+(const CBox& aBox) const; public: // Multiply a box by an integer CBox operator*(int n) const; public: // Divide one box into another int operator/(const CBox& aBox) const; }; You can edit or rearrange the code in any way that you want(as long as it’s still correct, of course. I have added a few empty lines to make the code a bit more readable. The contents of the Box.cpp file ultimately look something like this: #include “.\box.h” CBox::CBox(double lv, double wv, double hv) { lv = lv <= 0.0 ? 1.0 : lv; // Ensure positive wv = wv <= 0.0 ? 1.0 : wv; // dimensions for hv = hv <= 0.0 ? 1.0 : hv; // the object m_Length = lv>wv ? lv : wv; // Ensure that m_Width = wv<lv ? wv : lv; // length >= width m_Height = hv; } CBox::~CBox(void) { } // Overloaded addition operator CBox CBox::operator+(const CBox& aBox) const { // New object has larger length and width of the two, // and sum of the two heights return CBox(m_Length > aBox.m_Length ? m_Length : aBox.m_Length, m_Width > aBox.m_Width ? m_Width : aBox.m_Width, m_Height + aBox.m_Height); } // Multiply a box by an integer CBox CBox::operator*(int n) const { if(n%2) return CBox(m_Length, m_Width, n*m_Height); // n odd else return CBox(m_Length, 2.0*m_Width, (n/2)*m_Height); // n even 452 Chapter 8 11_571974 ch08.qxp 1/20/06 11:21 PM Page 452 } // Divide one box into another int CBox::operator/(const CBox& aBox) const { // Temporary for number in horizontal plane this way int tc1 = 0; // Temporary for number in a plane that way int tc2 = 0; tc1 = static_cast<int>((m_Length/aBox.m_Length))* static_cast<int>((m_Width/aBox.m_Width)); // to fit this way tc2 = static_cast<int>((m_Length/aBox.m_Width))* static_cast<int>((m_Width/aBox.m_Length)); // and that way //Return best fit return static_cast<int>((m_Height/aBox.m_Height))*(tc1>tc2 ? tc1 : tc2); } The shaded lines are those that you should have modified or added manually. The very short functions, particularly those that just return the value of a data member, have their defi- nitions within the class definition so that they are inline. If you take a look at Class View by clicking the tab and then click the + beside the CBox class name, you’ll see that all the members of the class are shown in the lower pane. This completes the CBox class, but you still need to define the global functions that implement operators to compare the volume of a CBox object with a numerical value. Adding Global Functions You need to create a .cpp file that will contain the definitions for the global functions supporting opera- tions on CBox objects. The file also needs to be part of the project. Click the Solution Explorer tab to display it (you currently will have the Class View tab displayed) and right-click the Source Files folder. Select Add > New Item from the context menu to display the dialog box. Choose the category as Code and the template as C++ File (.cpp) in the right pane of the dialog box and enter the file name as BoxOperators. You can now enter the following code in the Editor pane: // BoxOperators.cpp // CBox object operations that don’t need to access private members #include “Box.h” // Function for testing if a constant is > a CBox object bool operator>(const double& value, const CBox& aBox) { return value > aBox.Volume(); } // Function for testing if a constant is < CBox object bool operator<(const double& value, const CBox& aBox) { return value < aBox.Volume(); } // Function for testing if CBox object is > a constant 453 More on Classes 11_571974 ch08.qxp 1/20/06 11:21 PM Page 453 bool operator>(const CBox& aBox, const double& value) { return value < aBox; } // Function for testing if CBox object is < a constant bool operator<( const CBox& aBox, const double& value) { return value > aBox; } // Function for testing if a constant is >= a CBox object bool operator>=(const double& value, const CBox& aBox) { return value >= aBox.Volume(); } // Function for testing if a constant is <= CBox object bool operator<=(const double& value, const CBox& aBox) { return value <= aBox.Volume(); } // Function for testing if CBox object is >= a constant bool operator>=( const CBox& aBox, const double& value) { return value <= aBox; } // Function for testing if CBox object is <= a constant bool operator<=( const CBox& aBox, const double& value) { return value >= aBox; } // Function for testing if a constant is == CBox object bool operator==(const double& value, const CBox& aBox) { return value == aBox.Volume(); } // Function for testing if CBox object is == a constant bool operator==(const CBox& aBox, const double& value) { return value == aBox; } // CBox multiply operator n*aBox CBox operator*(int n, const CBox& aBox) { return aBox * n; } // Operator to return the free volume in a packed CBox double operator%( const CBox& aBox, const CBox& bBox) { return aBox.Volume() - (aBox / bBox) * bBox.Volume(); } You have a #include directive for Box.h because the functions refer to the CBox class. Save the file. When you have completed this, you can select the Class View tab. The Class View tab now includes a Global Functions and Variables folder that contain all the functions you just added. You have seen definitions for all these functions earlier in the chapter, so I won’t discuss their implemen- tations again. When you want to use any of these functions in another .cpp file, you’ll need to be sure that you declare all the functions that you use so the compiler will recognize them. You can achieve this by putting a set of declarations in a header file. Switch back to the Solution Explorer pane once more and right-click the Header Files folder name. Select Add > New Item from the context menu to display the dialog box, but this time select category as Code, the template asHeader File(.h), and enter the name as BoxOperators. After clicking the Add button an empty header file is added to the project, and you can add the following code in the Editor window: 454 Chapter 8 11_571974 ch08.qxp 1/20/06 11:21 PM Page 454 // BoxOperators.h - Declarations for global box operators #pragma once bool operator>(const double& value, const CBox& aBox); bool operator<(const double& value, const CBox& aBox); bool operator>(const CBox& aBox, const double& value); bool operator<(const CBox& aBox, const double& value); bool operator>=(const double& value, const CBox& aBox); bool operator<=(const double& value, const CBox& aBox); bool operator>=(const CBox& aBox, const double& value); bool operator<=(const CBox& aBox, const double& value); bool operator==(const double& value, const CBox& aBox); bool operator==(const CBox& aBox, const double& value); CBox operator*(int n, const CBox aBox); double operator%(const CBox& aBox, const CBox& bBox); The #pragma once directive ensures that the contents of the file are not included more than once in a build. You just need to add an #include directive for BoxOperators.h to any source file that makes use of any of these functions. You’re now ready to start applying these functions, along with the CBox class, to a specific problem in the world of boxes. Using Our CBox Class Suppose that you are packaging candies. The candies are on the big side, real jaw breakers, occupying an envelope 1.5 inches long by 1 inch wide by 1 inch high. You have access to a standard candy box that is 4.5 inches by 7 inches by 2 inches, and you want to know how many candies will fit in the box so that you can set the price. You also have a standard carton that is 2 feet 6 inches long, by 18 inches wide and 18 inches deep, and you want to know how many boxes of candy it can hold and how much space you’re wasting when it has been filled. In case the standard candy box isn’t a good solution, you would also like to know what custom candy box would be suitable. You know that you can get a good price on boxes with a length from 3 inches to 7 inches, a width from 3 inches to 5 inches and a height from 1 inch to 2.5 inches, where each dimension can vary in steps of half an inch. You also know that you need to have at least 30 candies in a box, because this is the minimum quantity consumed by your largest customers at a sitting. Also, the candy box should not have empty space, because the complaints from customers who think they are being cheated goes up. Further, ideally you want to pack the standard carton completely so the candies don’t rattle around. You don’t want to be too stringent about this otherwise packing could become difficult, so let’s say you have no wasted space if the free space in the packed carton is less than the volume of a sin- gle candy box. With the CBox class, the problem becomes almost trivial; the solution is represented by the following main() function. Add a new C++ source file, Ex8_08.cpp, to the project through the context menu you get when you right-click Source Files in the Solution Explorer pane, as you’ve done before. You can then type in the code shown here: 455 More on Classes 11_571974 ch08.qxp 1/20/06 11:21 PM Page 455 // Ex8_08.cpp // A sample packaging problem #include <iostream> #include “Box.h” #include “BoxOperators.h” using std::cout; using std::endl; int main() { CBox candy(1.5, 1.0, 1.0); // Candy definition CBox candyBox(7.0, 4.5, 2.0); // Candy box definition CBox carton(30.0, 18.0, 18.0); // Carton definition // Calculate candies per candy box int numCandies = candyBox/candy; // Calculate candy boxes per carton int numCboxes = carton/candyBox; // Calculate wasted carton space double space = carton%candyBox; cout << endl << “There are “ << numCandies << “ candies per candy box” << endl << “For the standard boxes there are “ << numCboxes << “ candy boxes per carton “ << endl << “with “ << space << “ cubic inches wasted.”; cout << endl << endl << “CUSTOM CANDY BOX ANALYSIS (No Waste)”; // Try the whole range of custom candy boxes for(double length = 3.0 ; length <= 7.5 ; length += 0.5) for(double width = 3.0 ; width <= 5.0 ; width += 0.5) for(double height = 1.0 ; height <= 2.5 ; height += 0.5) { // Create new box each cycle CBox tryBox(length, width, height); if(carton%tryBox < tryBox.Volume() && tryBox % candy == 0.0 && tryBox/candy >= 30) cout << endl << endl << “Trial Box L = “ << tryBox.GetLength() << “ W = “ << tryBox.GetWidth() << “ H = “ << tryBox.GetHeight() << endl << “Trial Box contains “ << tryBox / candy << “ candies” << “ and a carton contains “ << carton / tryBox << “ candy boxes.”; } cout << endl; return 0; } 456 Chapter 8 11_571974 ch08.qxp 1/20/06 11:21 PM Page 456 Let’s first look at how the program is structured. You have divided it into a number of files, which is common when writing in C++. You will be able to see them if you look at the Solution Explorer tab, which looks as shown in Figure 8-13. Figure 8-13 The file Ex8_08.cpp contains the main()function and a #include directive for the file BoxOperators.h that contains the prototypes for the functions in BoxOperators.cpp (which aren’t class members). It also has an #include directive for the definition of the class CBox in Box.h. A C++ console program is usually divided into a number of files that will each fall into one of three basic categories: 1. .h files containing library #include commands, global constants and variables, class defini- tions and function prototypes— in other words, everything except executable code. They also contain inline function definitions. Where a program has several class definitions, they are often placed in separate .h files. 2. .cpp files containing the executable code for the program, plus #include commands for all the definitions required by the executable code. 3. Another .cpp file containing the function main(). The code in our main()function really doesn’t need a lot of explanation— it’s almost a direct expression of the definition of the problem in words, because the operators in the class interface perform problem- oriented actions on CBox objects. The solution to the question of the use of standard boxes is in the declaration statements, which also compute the answers we require as initializing values. You then output these values with some explana- tory comments. 457 More on Classes 11_571974 ch08.qxp 1/20/06 11:21 PM Page 457 [...]... L = 5 W = 4 .5 H = 2 Trial Box contains 30 candies and a carton contains 216 candy boxes Trial Box L = 5 W = 4 .5 H = 2 Trial Box contains 30 candies and a carton contains 216 candy boxes Trial Box L = 6 W = 4 .5 H = 2 Trial Box contains 36 candies and a carton contains 180 candy boxes Trial Box L = 6 W = 5 H = 2 Trial Box contains 40 candies and a carton contains 162 candy boxes Trial Box L = 7 .5 W =... Solution Explorer pane immediately The code from h files is added at the beginning of the cpp files that require them as a result of the #include directives that you specify You need #include directives for header files containing standard library functions and other standard definitions, as well as for your own header files Visual C++ 20 05 automatically keeps track of all these files, and enables you to... variables in the Class View tab 459 Chapter 8 In a Windows program, there are other kinds of definitions for the specification of things such as menus and toolbar buttons These are stored in files with extensions like rc and ico Just like h files, these do not need to be explicitly added to a project because they are created and tracked automatically by Visual C++ 20 05 when you need them Naming Program... factor, (len1+len2)/factor); return 0; } The output from the example is: 6 feet 9 inches plus 7 feet 8 inches is 14 feet 5 inches 2 .5 times 7 feet 8 inches is 19 feet 2 inches 7 feet 8 inches times 2 .5 is 19 feet 2 inches The sum of 6 feet 9 inches and 7 feet 8 inches divided by 2 .5 is 5 feet 9 inches Press any key to continue How It Works The new operator overloading function in the Length class is... difference from native C++ classes is that functions that implement operator overloading in C++/ CLI classes can be static members of a class as well as instance members This means that you have the option of implementing binary operators in C++/ CLI classes with static member functions with two parameters in addition to the possibilities you have seen in the context of native C++ for operator functions... 30 candies and a carton contains 216 candy boxes You have a duplicate solution due to the fact that, in the nested loop, you evaluate boxes that have a length of 5 and a width of 4 .5, as well as boxes that have a length of 4 .5 and a width of 5 Because the CBox class constructor ensures that the length is not less than the width, these two are identical You could include some additional logic to avoid... creating h and cpp files to hold your program code from now on Segmenting a C++ program into h and cpp files is a very convenient approach, as it makes it easy for you to find the definition or implementation of any class, particularly if you’re working in a development environment that doesn’t have all the tools that Visual C++ provides As long as you know the class name, you can go directly to the... functions with one parameter or non-member functions with two parameters Similarly, in C++/ CLI you have the additional possibility to implement a prefix unary operator as a static member function with no parameters Finally, although in native C++ you can overload the new operator, you cannot overload the gcnew operator in a C++/ CLI class Let’s look into some of the specifics, starting with value classes... of each class, as you can see in Figure 8- 15 Figure 8- 15 460 More on Classes I adjusted the size of the Class View pane so all the elements in the project are visible Here, you can see the details of the classes and globals for the last example As mentioned before, double-clicking any of the entries in the tree takes you directly to the relevant source code C++/ CLI Programming Although you can define... arithmetic expressions You can write statements such as: Length Length Length Length len1 = Length(2,6); len2 = Length(3 ,5) ; len3 = Length(14,6); total = 12*(len1 + len2 + len3) // 2 feet 6 inches // 3 feet 5 inches // 14 feet 6 inches + (len3/Length(1,7))*len2; The value of total will be 2 75 feet 9 inches The last statement makes use of the assignment operator that comes with every value class as well as . length = 3.0 ; length <= 7 .5 ; length += 0 .5) for(double width = 3.0 ; width <= 5. 0 ; width += 0 .5) for(double height = 1.0 ; height <= 2 .5 ; height += 0 .5) { // Create new box each cycle CBox. as you’ve done before. You can then type in the code shown here: 455 More on Classes 11 _57 1974 ch08.qxp 1/20/06 11:21 PM Page 455 // Ex8_08.cpp // A sample packaging problem #include <iostream> #include. inches is 14 feet 5 inches 2 .5 times 7 feet 8 inches is 19 feet 2 inches 7 feet 8 inches times 2 .5 is 19 feet 2 inches The sum of 6 feet 9 inches and 7 feet 8 inches divided by 2 .5 is 5 feet 9 inches Press

Ngày đăng: 13/08/2014, 18:20

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan