LINKÖPINGS UNIVERSITET Department of Computer and Information Science Software and Systems Tommy Olsson 2015-04-07 Computer examination in TDDD38 Advanced Programming in C++ Exam code: DAT1 Date: 2015-04-09 Time: 14-19 On duty: Tommy Olsson, 28 1954 Teacher on duty will visit the locations approximately once every hour, and is otherwise only to be called upon for urgent matter, for example computer system problems. Administrator: Anna Grabska Eklund, 28 2362 Means of assistance: An English-* vocabulary may be brought to the exam. cplusplus.com Reference, se instructions for how to browse. Scrap paper and pen is allowed. No other means of assistance (printed or electronic) are allowed. Grading: Each theory question is worth 1 credit, each programming problem 5 credits; total 25: 0-10 for grade U/FX, 11-14 for grade 3/C, 15-18 for grade 4/B, and 19-25 for grade 5/A. Instructions: Don’t log out at any time during the exam, only when you have finished. Given files are found in subdirectory given_files (write protected). Theory questions answers and program solutions files shall be left, either in the home directory, or in subdirectory Desktop. Use given file names, upper and lower case is significant! In case names for program entities are specified, use those exactly as given. When using standard library components, such as algorithms and containers, try to chose “best fit” regarding the problem to solve. Avoid unrelated/unnecessary computations and unnecessary data structures. C style coding may cause point reduction when there are C++ alternatives. Follow specifications – design with care – use C++ properly! Good luck! TDDD38 Advanced Programming in C++ 2 (6) Theory questions Copy THEORY.TXT from directory given_files to the home directory (if you prefer working there): cp given_files/THEORY.TXT . or to subdirectory Desktop (if you prefer working there): cp ../given_files/THEORY.TXT . Fill in your personal data at the top of the file, and give your answers to the theory questions below in that file. 1. A member function can be declared as const or non-const. What does such a const declaration mean? Why is it so important to declare a member function const, whenever possible? (Which are the implications?) ❏ 2. Give at least three examples of how normal function parameters and template parameters, either differ or have alike properties/features. ❏ 3. Suppose we use objects of some derived type in a program and we have noticed that the destruction of such objects does not always work properly. Give a good explanation to this, and also a scenario where this would occur. ❏ 4. In which ways can type conversion for a class type be defined? ❏ 5. What is a function object? To maximize the usability, what should one think of in general when defining a function object? ❏ TDDD38 Advanced Programming in C++ 3 (6) Programming problems 6. Copy program6.cc from given_files. The file contains instructions for how to create objects and testing. Design a polymorphic class hierarchy for handling viewing card units, such as CA Modules (conditional access modules) and digital television (DTV) tuners (set-top boxes). • VC_Unit (viewing card unit) shall be an abstract base class for all VC unit classes. It shall store the name of the manufacturer (std::string), and the price (double). When a VC_Unit object is initialized, a value for the manufacturer shall always be given. The price is optional, if not given it is to be initialized to 0.0. After initialization, only the price shall be possible to modify. VC_Unit shall have two direct subclasses, CA_Module and DTV_Box, se below. • CA_Module shall be a concrete class for CA module objects, which beside manufacturer name and price, shall store which CA system (conditional access system) the module is supporting, for example Conax or Viaccess (std::string). The CA system is, together with other required initial values, to be given when a CA_Module object is initialized, and thereafter not to be changed. • DTV_Box shall be a concrete class for DTV boxes, which beside manufacturer name and price, shall store the model of the unit (std::string). The model is, together with other required initial values, to be given when a DTV_Box object is initialized, and thereafter not to be changed. DTV_Box shall have one subclass, DTV_Box_Recordable. • DTV_Box_Recordable shall be a concrete class for DTV boxes with a built-in disk. Beside the manufacturer name, the price, and the model, a DTV_Box_Recordable object shall also store the size of the disk (an int representing the size in Gigabytes). The disk size is, together with other required initial values, to be given when an object of type DTV_Box_Recordable is initialized, and thereafter not to be altered. Objects are supposed to always be created dynamically, and handled with pointers. There shall be a public get function for every data member of a class. For price only there shall be a public set_price(price) function. A public member function clone() shall be the only public way to make a copy of objects, including assignment. clone() shall create a dynamically allocated object and return a pointer to the new object. The copy shall be created using the copy constructor Special member functions to be allowed, and the compiler can generate shall be defaulted; special member functions which are not to be allowed, and the compiler will generate shall be deleted; special member functions which are not to be allowed, and the compiler will not generate shall not be declared. No other member functions than those mentioned above are allowed! Example of expected output from the test program: Dilog CA module, Viaccess [499.00] Samsung DTV box, DTB-P850V [2495.00] Samsung Recordable DTV Box, DTB-P770V PVR, 80GB [2595.00] ”Dilog“ and ”Samsung“ are manufacturers, ”CA module“, ”DTV box“, and ”Recordable DTV Box“ are different kind of VC units, ”DTB-P850V“ and ”DTB-P770V PVR” are model designations, ”Viaccess” is a CA system notation, and ”80GB” is a disk size. Prices are shown within square brackets. Design with care – use C++ well – keep with the given specifications! ❏ TDDD38 Advanced Programming in C++ 7. 4 (6) Write your code on a file named program7.cc. Please note! Standard library components shall be used whenever possible, and always try to find “best fit”. Avoid hand-written loops (for, while or do, including range for even if such could be a good alternative), use standard algorithms when suitable. If user defined function is required, use lambda expression or function object, not a normal function. Unordered positive and negative integer values are supposed to be given, in free format, on a text file. There is such an input file, seven.txt, in directory given_files, When the program is started, the name of the input file is to be given on the command line, for example: a.out given/files/seven.txt All output is to be printed to the standard output stream cout. The program shall do the following, step by step, and in each step, no more, no less than what is specified! Mark the beginning of each step with a comment on the form // 1, // 2, and so on. 1) Check the command line. If not correct, print an error message and terminate the program. 2) Open an input file stream for the file named given on the command line. If the file cannot be opened, print an error message and end the program. 3) Read values from the input file and store in a suitable sequence container, regarding what to be done below, in the same order as the values are read from the file. 4) Print the values in the container, each followed by a space character. 5) Use standard algorithm for_each and a component of your own to, at the same time, make all negative numbers in the container positive and count how many negative numbers there are. Print how many negative numbers there were. 6) Print the element in the container, each followed by a space character. 7) Move the five smallest numbers to the beginning of the container, in ascending order; the order of the rest of the elements is arbitrary. Print the five smallest elements in the container. 8) Remove the five smallest numbers from the container. Print the remaining elements in the container, each followed by a space. Program output should be as follows (as specified in step 4, 5, 6, 7, and 8): Numbers read: 1 9 -17 -8 -4 -7 7 14 21 -1 -9 11 -12 10 1 7 negative values were found. After making all numbers positive: 1 9 17 8 4 7 7 14 21 1 9 11 12 10 1 Five smallest numbers: 1 1 1 4 7 Five smallest numbers removed: 17 9 14 21 8 9 11 12 10 7 ❏ TDDD38 Advanced Programming in C++ 8. 5 (6) Copy program8.cc from given_files. There are some instructions and test cases given in the file. A class Constrained_Value is given (there are possible improvements to this definition, but it’s sufficient for our purposes). • The type converting operator function is for convenience, to make it easy to print the value of a Constrained_Value object. • Constrained_Value shall have the full set of special member functions, but don’t declare anything that the compiler will generate automatically, to keep the public interface minimal. We want to be able to supply a constraint policy for the data member value, for example to keep value odd, even if initializing or assigning to an even value x. Therefore make Constrained_Value a template, to be able to supply a policy as template argument. If we have a policy class named Odd_Numbers_Policy, an instance named odd for that policy shall then be declared: Constrained_Value<Odd_Numbers_Policy> odd; In this case the initial value cannot be 0, since 0 is not odd. Instead we let the policy class define a default value as a nested data member, named default_value, with the value 1 in this case. We also want to be able to select the type for data member value, but not the usual way. Instead the policy class shall have a nested type for this, named value_type. The constraint shall be implemented as a member function of the constraint class, named assign(), with two parameters and returning nothing. When an operation in Constrained_Value, is to initialize or assign the member value, it shall call the policy function assign(): assign(x, value); // sets x to value, according to the policy in question After this value should be x, but only if x fulfils the constraint that assign() implements. Otherwise some action is taken to make value conform to the policy, or something else happens, depending on the policy in question. Define two policy classes: Odd_Numbers_Policy shall be a non-template. It shall declare the type for value to be int, and the default value to be 1. The constraint is that value shall be odd. If initialized or assigned to something even, rounding towards zero is to be performed, i.e. subtract 1 if x > 0, add 1 if x < 0. Example: Constrained_Value<Odd_Numbers_Policy> odd(0); // value initialized to 1 Range_Throwing_Policy shall be a template with two non-type parameters, one for a lower bound and one for an upper bound, defining an allowed range for value. If the constraint is not fulfilled, std::range_error shall be thrown. Range_Throwing_Policy shall declare the type for value to be int, and the default value to be the lower bound. Example: Constrained_Value<Range_Throwing_Policy<0, 23>> hour; Hint: static_assert could come handy for checking that upper bound is not less than lower bound. ❏ TDDD38 Advanced Programming in C++ 9. 6 (6) Copy program9.cc from given_files. There is a design pattern named Singleton, for controlled access to a single instance of an object. One possible implementation of a Singleton is to encapsulate the object in question in a class, and make the class responsible for ensuring that it (the class itself) is only created in a sole instance, and thereby also only a sole instance of the controlled object (the actual singleton). Design a class template Singleton, with one template type parameter T for the kind of object the singleton is to control. Different instances, for example Singleton<int> and Singleton<string> are regarded as distinct singletons, so there shall be one singleton for each distinct type T. Singleton shall have: • a public member function instance(), as the only way to create an instance of itself, if not already created, and also to give access to the instance. instance() shall return a pointer to the instance. • a public member function access() to access the controlled object, which can be given either as an accessor member function and a modifier member function, or as one combined accessor/ modifier member function. Your choice! • a public member function destroy(), to destroy the controlled object properly. The code in main() in the given file shows how to handle and operate upon Singletons. Singletons shall not be copyable or assignable. ❏