← Back to 24T3

Tutorial 2: Classes

MTRN2500 24T3


Tutorial Slides


Intro to Classes

  1. Define the following terms:
  1. Discuss the following concepts and how they relate to classes:
  1. What is a constructor? What is a default constructor?
  1. What does the this keyword refer to in C++?
  1. Suppose we want to implement a simple class Student to represent a UNSW student with a zid ( unsigned int ) and name ( std::string ).

a. Declare the class in Student.hpp. Include a constructor that initializes the class’s attributes, and ensure that the correct access modifiers are used.

b. In a file main.cpp, show how the construtor for the Student class (defined above) can be invoked.

c. In a file Student.cpp, implement getters and setters for each of the attributes of the Student class. Add the function prototypes to Student.hpp and ensure that “const-correctness” is maintained (i.e., use const wherever appropriate). What is the benefit of using getters and setters over making the attributes public?

d. In main.cpp, print out the instantiated Student object’s zid and name.

e. Modify Student.hpp to add another constructor that takes only the zid as an argument and sets the name to “Unknown”.

f. Explicitly delete the default constructor for the Student class. What happens when you try to instantiate a Student object without any arguments?

g. On second thought, I want to prevent the zid from being modified after the Student has been created. How can I achieve this?

Structs vs. Classes

  1. What is the difference between a struct and a class in C++?

Classes: Common Errors

  1. Will this code compile despite not calling the constructor for MyClass ? If yes, explain why and describe the output. If no, explain why not.
#include <iostream> class MyClass { public: int getVar() const { return mVar; } int getVar2() const { return mVar2; } private: int mVar = 42; int mVar2; }; int main() { MyClass myObject; std::cout << myObject.getVar() << std::endl; std::cout << myObject.getVar2() << std::endl; }
  1. What is the compiler error in the following program? How can it be fixed?
#include <iostream> class MyClass { int mVar = 3; }; int main() { MyClass myObject; std::cout << myObject.mVar << std::endl; }
  1. What is the compiler error in the following code? How can it be fixed?
class MyClass { public: int getVar(); private: int mVar = 3; }; int getVar() { return mVar; } int main() { MyClass myObject; }
  1. What is the compiler error in the following code? How can it be fixed?
class MyClass { public: MyClass(int var) { mVar = var; } private: const int mVar; };
  1. What is the compiler error in the following code? How can it be fixed?
class MyClass { public: MyClass() : mVar(0) {} MyClass(int var = 0) : mVar{var} {} private: int mVar; };
  1. What is the compiler warning in the following code? How can it be fixed?
class MyClass { public: MyClass(int a, double b) : mVar2{b}, mVar1{a} {} private: int mVar1; double mVar2; };
  1. What is the mistake in this code? How can it be fixed?
class Person { public: void setAge(int age) { age = age; } private: int age = 0; };
  1. What is the compiler error in the following code?
#include <iostream> class Line { public: Line(int length) : mLength{length} {} int getLength() const { return mLength; } void setLength(int length) { mLength = length; } private: int mLength; }; int main() { const Line l(5); l.setLength(10); std::cout << l.getLength() << std::endl; return 0; }

Arrays and Vectors

  1. What is the difference between std::array and std::vector in C++? When would you use one over the other?
  1. When comparing the difference between std::array and std::vector , illustrate how their memory is layed out.
  1. Both std::array and std::vector can be indexed with the index operator [] or with the at() method. What is the difference between the two methods? Declare a std::array and a std::vector and demonstrate the difference.
  1. Let’s add functionality to the Student class (defined above) that allows us to keep track of a student’s course grades.

a. Add a private member variable to the Student class to store a list of the student’s grades (which are of type int). Would a std::array or std::vector be more appropriate for this use case?

b. Add a method to the Student class that allows us to add a grade to the student’s list of grades (addGrade), and another method to calculate their WAM (calculateWAM). Implement these methods in Student.cpp. Assume that all courses have equal weight. What edge case(s) do we have to handle? Decide on an appropriate return value in this case.

Strings

  1. Refactor the following C-style program to C++ using std::string . The program should read in an input string and output it as uppercase. You can assume that the input string contains only lowercase alphabetic characters.
#include <stdio.h> int main() { char input[100]; printf("Enter a string: "); scanf("%s", input); char output[100] = {0}; for (int i = 0; input[i] != '\0'; i++) { output[i] = input[i] + 48; } printf("Original string: %s\n", input); printf("Uppercase string: %s\n", output); return 0; }
  1. Complete the following function that takes a std::string and returns the number of ‘special characters’ in the string. Special characters are characters in the SPECIAL_CHARACTERS constant expression.

For example, if SPECIAL_CHARACTERS = "hl", then countSpecial("hello") == 3 (the two l and one h characters).

const std::string SPECIAL_CHARACTERS = "aeiouy"; int countSpecial(const std::string str);

Pairs & Tuples

  1. Represent a 2D point with real coordinates using a std::pair . Write a function that takes two std::pair objects representing points and returns the Euclidean distance between them and the midpoint of the line segment connecting them as a std::pair<double, std::pair<double, double>> .
#include <utility> std::pair<double, std::pair<double, double>> distanceAndMidpoint(std::pair<double, double> p1, std::pair<double, double> p2);

You may also use typedef to represent the 2D point using a std::pair.

  1. Let’s further improve the Student class above. Instead of storing only the grades of a student, we want to store the grades, the corresponding course names and course code.

a. Modify the Student class member variables to store this information (hint: use a std::tuple). Modify the addGrade method to also take the course name and code as arguments. Update the calculateWAM method to work with the new data structures. Implement the changes in Student.hpp and Student.cpp.

b. Add a new method printTranscript to the Student class that prints out the course code, course name, and grade for each course the student has taken to stdout. Implement this method in Student.cpp.

Each line of output should be formatted as follows:

<Course Code> - <Course Name>: <Grade> MTRN2500 - Computing for Mechatronic Engineers: 87

Enums

  1. What is the difference between an enum and an enum class in C++?
enum class Colour { red, green, blue }; enum Animal { dog, cat, bird, human };
  1. Below is a function that takes in an int representing a day of the week ( 1 representing Monday, 2 representing Tuesday, etc.). It prints out “It’s a weekday!” if the day is Monday to Friday, and “It’s the weekend!” if the day is Saturday or Sunday.
#include <iostream> void printDay(const int day) { switch (day) { case 1: case 2: case 3: case 4: case 5: std::cout << "It's a weekday!" << std::endl; break; case 6: case 7: std::cout << "It's the weekend!" << std::endl; break; default: std::cout << "Invalid day" << std::endl; break; } }

A potential weakness of this function is that it will accept any integer as input, even if it is not a valid day of the week (e.g. printDay(0) or printDay(-5)). Refactor this function to use an enum to represent the days of the week and only accept valid days as input.

Testing with Catch2

Catch2 is the testing framework you will use in Assignment 1 to write tests for your code.

  1. Where can you find the documentation for the Catch2 testing framework?
  1. Write some tests using the Catch2 testing framework to test the Student class that we have implemented. Write basic tests for the constructor, getters and setters, and the calculateWAM method.

What do we need to consider when comparing floating point numbers? How can we handle this in our tests?

[aside] const-overloading

  1. Discuss const -overloading in C++. Here is a simple example to illustrate:
#include <iostream> class MyClass { public: void print() const { std::cout << "Const" << std::endl; } void print() { std::cout << "Not const" << std::endl; } }; int main() { MyClass m; m.print(); const MyClass cm; cm.print(); return 0; }