Educational Objectives. After successfully completing this assignment, the student should be able to accomplish the following:
Operational Objectives: Define and implement the class Product and deliver the code in two files product.h and product.cpp along with a makefile for the supplied test harness.
Deliverables: product.h, product.cpp, makefile, log.txt
build: id.o [0..2]: x test1.o [0..2]: x test2.o [0..2]: x test1.x [0..2]: x test2.x [0..2]: x Producttest1.x [0..2]: x Producttest2.x [0..2]: x test: Producttest1.x [0..10]: xx Producttest2.x [0..10]: xx code: constructor 0 [0..1]: x init list [0..1]: x constructor 2 [0..1]: x init list [0..1]: x copy constructor [0..1]: x init list [0..1]: x destructor [0..1]: x assignment operator [0..1]: x engineering etc: requirements [-20..4]: x # note negative points awarded during assessment coding standard [-20..4]: x # note negative points awarded during assessment dated submission deduction [2 pts per]: ( x) # note negative points awarded during assessment -- total [0..50]: xx
See lecture notes Chapter 4. Classes Part 1, Chapter 5. Pointers, Chapter 6. Classes Part 2, and Chapter 7: C-Strings.
Begin as usual by creating your assignment directory and copying the distribution files for the assignment:
cp ~cop3330p/LIB/proj2/* ~/cop3330/proj2/ cp ~cop3330p/LIB/area51/Product*.x ~/cop3330/proj2/ cp ~cop3330p/LIB/scripts/submit.sh ~/cop3330/proj2/
Then a long listing of your assignment directory should look like this:
-rw------- 1 xxxxxxxx CS-Class 505 Sep 14 11:45 submit.sh -rw------- 1 xxxxxxxx CS-Class 505 Sep 14 11:45 deliverables.sh -rw------- 1 xxxxxxxx CS-Class 16469 Sep 14 11:46 Producttest1.x -rw------- 1 xxxxxxxx CS-Class 13355 Sep 14 11:46 Producttest2.x -rw------- 1 xxxxxxxx CS-Class 12216 Sep 14 11:46 Producttest2ShallowCopy.x -rw------- 1 xxxxxxxx CS-Class 2030 Sep 14 11:45 test1.cpp -rw------- 1 xxxxxxxx CS-Class 1306 Sep 14 11:45 test2.cpp
The area51 executables are for demonstration purposes. You can erase these and get them back by copying again. After invoking "clean ." to declutter the directory and "chmod 700 submit.sh" to set permissions on the submit script, a long listing should be:
-rwx------ 1 xxxxxxxx CS-Class 505 Sep 14 11:45 submit.sh -rw------- 1 xxxxxxxx CS-Class 505 Sep 14 11:45 deliverables.sh -rw------- 1 xxxxxxxx CS-Class 2030 Sep 14 11:45 test1.cpp -rw------- 1 xxxxxxxx CS-Class 1306 Sep 14 11:45 test2.cpp
(The steps involving submit.sh may be skipped if you already have submit.sh executable in ~/.bin.)
Now continue to the next step:
Begin a log file named log.txt. This should be an ascii text file in cop3330/proj2 with the following header:
log.txt # log file for UIntSet project <date file created> <your name> <your CS username>
This file should document all work done by date and time, including all testing and test results.
Create a makefile that builds executables test1.x and test2.x. Look at the #include statements in test1.cpp and test2.cpp to deduce what the intermediate targets and dependencies should be.
Design the class Product, placing the definition in file product.h
Implement the class Product, placing the class implementation in file product.cpp. You can test the code for syntax errors with the command "make product.o" or the command "co3330 product".
Thoroughly test class Product, starting out with the supplied test harnesses in file proj2/test?.cpp using your makefile to build the executables. (Note - you could also use the command line compile scripts "co3330" to create object files and then and "g++ -otest1.x product.o test1.o" to create executables, as in Project 1.)
Turn in product.h, product.cpp, and makefile using the submit.sh submit script.
Warning: Submit scripts do not work on the program and linprog servers. Use shell.cs.fsu.edu to submit projects. If you do not receive the second confirmation with the contents of your project, there has been a malfunction.
The class should implement the following diagram:
Class Name: | Product |
Services : |
void SetName ( const char* ) // sets the name field void SetBarCode ( uint32_t ) // sets the bar code field void SetCost ( float ) // sets the cost field const char* GetName () const // returns a const pointer to the name field uint32_t GetBarCode () const // returns the bar code by value float GetCost () const // returns cost by value |
Properties : |
Constructable: objects can be declared as ordinary variables Assignable: objects can be assigned one to another Passable: objects can be passed by value to and returned as values from functions |
Private variables: |
char * name_ // the product name uint32_t code_ // the product bar code float cost_ // the product cost |
The class should be a proper type, to include default constructor, 3-argument constructor (that initializes the three data fields), copy constructor, assignment operator, and destructor. Note that the default constructor should set the name to "#", the bar code to 0x00000000, and the cost to 0.0. The unit32_t type is defined in the cstdint library.
Be sure to use initialization lists for all of the constructors, including the copy constructor.
The output operator operator<< should be overloaded for the type Product. Display the three fields with TAB character between them. (Don't output any newlines.) (See Hint below.)
Class Product should pass testing with the supplied proj2/test?.cpp with no compile or runtime errors and no compiler warnings when the warning flags -Wall and -Wextra are set. The test compiler is clang++ -std=c++11 on linprog. This compiler and library is as close to compliance with c++11 as we have available.
Building and running the supplied proj2/test?.cpp should result in output identical to the supplied executable area51/Producttest?.x [? = 1 or 2] .
Hints
Note that the product name of p1 has changed (as you would expect after assignment p2 = p1), but the program "crashes" with a message "double free or corruption". What has happened is that the assignment operator made a "shallow copy" of the product name string. As the program terminates, the Product destructor is called for both p2 and p1, which results in a call to delete[] name_. Because of the shallow copy, delete[] is called twice on the same allocation, which generates the error.lacher@linprog2.cs.fsu.edu:~/3330/proj2>test2d.x Products after declaration: p1 = product_1 FEDCBA98 100.00 p2 = product_2 89ABCDEF 200.00 Products after assignment p2 = p1 p1 = product_1 FEDCBA98 100.00 p2 = product_1 FEDCBA98 100.00 *** glibc detected *** test2d.x: double free or corruption (fasttop): 0x0000000004b5e010 *** ======= Backtrace: ========= ...
It would be a good idea to understand this code as much as possible now, and then return to it after we cover C++ I/O.std::ostream& operator << ( std::ostream& os , const Product& p) { std::ios_base::fmtflags flags = os.flags(); os.setf(std::ios::fixed | std::ios::showpoint); // prep for $ output os.precision(2); os << p.GetName() << '\t' << std::hex << std::uppercase << std::setfill('0') << std::setw(8) // prep for hex output << p.GetBarCode() << std::dec << std::setfill(' ') << '\t' // return dec output << p.GetCost(); os.setf(flags); // return flags to previous states return os; }