1. A
    1. API
    2. ASAN
    3. Access specifiers
  2. C
    1. Constructor
    2. const
  3. G
    1. GDB
    2. g++
  4. M
    1. Make
    2. Memory Leak
  5. P
    1. Pointer
  6. R
    1. Recursion
  7. S
    1. std
  8. V
    1. Valgrind
Completed: / exercises

LAB_INTRO: Introduction To Classes in C++

Due date: 2024-03-18 23:59.
The very first data structure you'll create is a class designed to store a single RGB pixel. The implementation of this class as well as two functions are missing from the set of files, classes, and functions that we provide to you below. Your assignment is to complete the missing parts.

Download The Provided Files

Before you start working on your implementation, please make sure to download the necessary files from the provided link. The files can be found at lab_intro.zip.
Once you download the package, move it to your home directory in WSL. Next, you can uncompress the .zip file from Windows as you normally would, or from the WSL with:
unzip lab_intro.zip 
However, you may not have zip/unzip installed yet:
sudo apt install zip

Provided Files

Once you uncompressed the provided file, the code for this lab will reside in the lab_intro directory. Get there by typing the following line in the terminal while in your working directory:
cd lab_intro/
You should have the following files in your lab_intro directory now:

References for the Linux Command Line and Text Editor

If you need a refresher on the Linux command line and text editors refer to these resources for help:
  1. Setup Instructions: Linux Command Line
  2. Setup Instructions: Text Editors

Writing Your First Class: RGBAPixel

Inside the provided files rgbapixel.h, rhbapixel.cpp, define a class called RGBAPixel. As you will use this class a lot throughout the next labs, its API is intentionally simple. The class should contain four public member variables:
Make sure that all of the members of the class are public. Following convention, the class definition should be placed in a file called rgbapixel.h, and the member function implementations should be placed in a file called rgbapixel.cpp.
Additionally, you need to implement two constructors for the RGBAPixel class:

Writing the PNG Manipulation Functions

In this lab you will be tasked with implementing two functions within the main.cpp file, namely brighten and blendImages.
To give you an idea of how to write your own function, here's a sample function, which makes the image more green:
PNG getGreenComponent(PNG original)
   for (int x = 0; x < original.width(); x++)
      for (int y = 0; y < original.height(); y++)
         original(x, y)->red = 0;
         original(x, y)->blue = 0;
   return original;

Common Mistakes

To ensure that your code compiles, keep the following tips in mind. Remember to apply these tips not only while working on the current lab, but also in the future labs.

Read the Instructions Carefully

Make sure to pay close attention to the specifications we've provided. To avoid compilation errors, check that the file names, executable names, program output, and public member functions are exactly as we asked. A single typo can result in a compilation error. Don't worry though, testing your code with the provided output will help you catch and correct such mistakes.

Make Sure You Include Relevant Libraries

Make sure you define uint8_t type before declaring variables of this type. For that, you will want to include the standard library header file which contains the uint8_t type. You can include the header by doing the following in rgbapixel.h:
#include <cstdint>
using std::uint8_t;
If you don't do this you will probably get a compilation error about uint8_t not referring to a valid type. In the future, always make sure you include all of the relevant libraries in your code.

Install libpng Library

If your Linux installation is missing libpng library, the code won’t compile until you install it:
sudo apt install libpng-dev

Use Double Inclusion Guards in All Headers

To avoid compilation errors resulting from the inclusion of header files multiple times, it's essential to use double inclusion guards. In the past, students have forgotten to include these, which resulted in compilation failures. Therefore, make sure to use double inclusion guards consistently to prevent any such errors.
Here's an example of how to use double inclusion guards for a header file named myfile.h:
#ifndef MYFILE_H
#define MYFILE_H
// ... code goes here
The first line checks if the macro MYFILE_H has not been defined before, which is true if this is the first time myfile.h is being included in the compilation process. If it's true, then the rest of the code in the header file is compiled. If myfile.h is included multiple times, the macro will already be defined, and the code within the #ifndef and #endif statements will be ignored.
It is important that you remember to use double inclusion guards for all header files you create. For example, make sure you use them in your rgbapixel.h file (with RGBAPIXEL_H replacing MYFILE_H for clarity).

Other Provided Files

There are other helpful functions in the files we provided that you might want to look at or use in your code. These are the public member functions of the PNG class that are defined in png.h and png.cpp files.

Compiling the Code

To compile your code, type the following command into your terminal:
If there are no error messages generated on the screen, then your code compiled correctly.

Running the Code

After compiling your code, an executable named lab_intro should have been created in your working directory. You can now execute this file and test your code. To run the executable file use the following command prompt:
This will result in a png file named output.png created in your working directory. The easiest way to view the image is to open it in Windows.

Testing Correctness of Your Code

After running the executable, an output file named output.png will be generated. To test your program for correctness, we have provided a correct output file with the name target_output.png in the same directory. You can compare the two PNG files using the following command:
diff target_output.png output.png
If your output file is correct, there should be no differences reported between the two files. If it is incorrect, keep in mind that the images have to match exactly, so follow the assignment instructions exactly and do not change the main function in a way that affects the output. Once you have confirmed the correctness of the output file, you can submit your solution to us below.

Submitting Your Work

You can now upload your rgbapixel.h, rgbapixel.cpp, and main.cpp in the box below. To complete this lab, it isn't necessary to edit any other file.
Double check that you implemented the class called RGBAPixel, with public member variables red, green, blue, alpha, and two constructors. In main.cpp file you should have two new functions, brighten and blendImages.

Allowed filenames: main.cpp, rgbapixel.cpp, rgbapixel.h

Warning: You have not logged in. You cannot answer.


We would like to express our gratitude to prof. Cinda Heeren and the student staff of the UIUC CS Data Structures course for creating and sharing the programming exercise materials that have served as the basis for the labs used in this course.
Revised by: Elmeri Uotila and Anna LaValle
API stands for Application Programming Interface. In the context of this course, you can consider the header files to be such interfaces, as they determine what class functions and properties are public and thus accessible from anywhere.
AddressSanitizer (ASAN) is a memory error detector for C/C++. In this course, the makefiles will typically compile an executable that uses ASAN, with "-asan" at the end of its name.
The two notable access specifiers are:
  • public: class members defined after the public keyword are accessible from outside the class.
  • private: class members are generally private by default and thus not accessible from the outside
Constructor is a special non-static member function of a class that is used to initialize objects of its class type. A constructor is called upon initialization of an object. A constructor without arguments is a default constructor, but constructors that take arguments can be defined.
GDB, the GNU Project debugger, allows you to see what is going on `inside' another program while it executes -- or what another program was doing at the moment it crashed.
GDB can do four main kinds of things (plus other things in support of these) to help you catch bugs in the act:
  • Start your program, specifying anything that might affect its behavior.
  • Make your program stop on specified conditions.
  • Examine what has happened, when your program has stopped.
  • Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another.
GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files. Make gets its knowledge of how to build your program from a file called the makefile, which lists each of the non-source files and how to compute it from other files. When you write a program, you should write a makefile for it, so that it is possible to use Make to build and install the program.
Memory leak means that the program is not freeing up memory it reserves. The memory will be freed when the program terminates, but if a program keeps leaking more and more memory without terminating, it can become a huge issue!
A typical way for memory leaks to occur is reserving memory with new and not calling delete before the pointer goes out of scope.
Pointer variables store a memory address as their value. In other words, they point to some data. The data can be accessed by dereferencing the pointer. (Either like *p or p->...)
A recursive function calls itself from within it. The recursion call must be conditional or it would lead to an infinite loop.
Valgrind is another tool besides ASAN that you can use in this course. It can detect many memory-related errors that are common in C and C++ programs and that can lead to crashes and unpredictable behaviour.
const is a keyword meant to mark something as immutable
  • A const object cannot be modified: attempt to do so directly is a compile-time error, and attempt to do so indirectly (e.g., by modifying the const object through a reference or pointer to non-const type) results in undefined behavior.
  • const keyword on an object's member function prevents the object from being modified in the function
  • Pointer declarations can have 2 const keywords, one to make the data that's pointed at unable to be modified and one to make the pointer itself unable to be modified
Using const improves code readability and prevents accidental modification of objects.
g++ is a C++ compiler that we primarily use for this course. It is the C++ compiler for the GNU compiler collection. You may sometimes see gcc being used instead of g++, which was originally the GNU C compiler, but calling gcc generally also compiles .cpp files as C++. However, calling g++ is preferred.
In C++, std stands for Standard Library, which is a collection of commonly useful classes and functions. Typically, these are defined in the std namespace.