<jupyter_start><jupyter_text>Objects  Introduction You will read more than once that C++ is an **object oriented** programming language. This is, C++ has the ability to deal with **object** and **classes** (they are equivalent names for the same thing). An **object** is just data and operations you can perform with that data that are together within the same infrastructure. As an example, imagine we have a store, and that we want to write something to check the stock. In our store, we have several things we sell, but each thing has several properties in comon with different values:- Name- Price- Number of items availableDealing with objects in the store would be annoying without classes. If we have a **class** called `item`, we can store information about each type of item, which is the price, and how many items we have left. Actually, during this workshop, you have already used classes without knowing it, such as `vector` or `string`.  In C++, do define a class is as simple as:```c++class Item {  public:    // Mutators or Setters    void SetName(std::string name);    void SetPrice(double price);    void SetNumItems(int num_items);        // Accessors or Getters    std::string GetName();    double GetPrice();    int GetNumItems();  private:    // Class members    std::string name_;    double price_;    int num_items_;};```Let's analyze this step by step. ```c++class Item {```This first part sets the name of the class. The name of a class should be capitalized, without spaces/underscores, and if composed by several names, capitalize only the first letter of each word. ```c++  public:```This `public:` means that once you create the class, you will be able to access everything that is after it. An example would be the `size()` subrouting of a vector or a string. You create the `vector` and then you can access the function `size()`.```c++    // Mutators or Setters    void SetName(std::string name);    void SetPrice(double price);    void SetNumItems(int num_items);```The **mutators** or **setters** are member functions or subroutines in your class that allow to modify variables of the class. In this example, we have 3 different functions that set three different variables. If a function is a setter, you usually start the function name with `Set...`, but there can be other type of functions that access the data like a print, calculate, ... ```c++    // Accessors or Getters    std::string GetName();    double GetPrice();    int GetNumItems();```The **accessors** or **getters** are functions that allow to obtain the content of variables of the class. Usually, you start them with `Get...`. ```c++  private:```The `private:` keyword makes everything that is after it not accessible from the outside. **It is usually a good practice to make all the member variables private and only allow their modification via setters and getters**. Sometimes, one might add some private helper functions to the class. Not only the standard variables can be private, but there can also be functions or subroutines that are private.```c++    // Class members    std::string name_;    double price_;    int num_items_;};```Finally, we have the **class member variables**. These variables should be private, and they contain the information of the class. Note that all the variables that belong to the class end with `_`. This is a common practice to differenciate variables that belong to the class from variables defined and declared in the class functions. It is not mandatory, but strongly recommended to improve readability of the code. In the class previously defines, we have declared the functions, but we have not defined them. Usually, we make the class declaration in the header file, and the class definition in the source file. The header file should contain all the information about the class, its member functions and its member variables, properly commented and documented. Let's look at the following example, which creates the item class and uses it in the main:<jupyter_code>!gedit src/item_v1.h
!gedit src/item_v1.cpp
!gedit src/main_item_v1.cpp
!g++ -o item_v1.exe src/main_item_v1.cpp src/item_v1.cpp 
!./item_v1.exe<jupyter_output><empty_output><jupyter_text>Examples As an exercise, add a member function called `PrintItem()`, so it prints all the information of a given item. Modify the main function accordingly.<jupyter_code>!gedit src/item_v2.h
!gedit src/item_v2.cpp
!gedit src/main_item_v2.cpp 
!g++ -o item_v2.exe src/main_item_v2.cpp src/item_v2.cpp
!g++ -o item_v2_sol.exe src/main_item_v2_sol.cpp src/item_v2_sol.cpp
print("Your answer:")
!./item_v2.exe
print("\nSolution:")
!./item_v2_sol.exe<jupyter_output><empty_output><jupyter_text>Constructors When we declare a class, none of its member variables are initialized unless we specify it. What is actually happening is that the code is calling the **default constructor**, which declares all the variables in the class, but does nothing else. It is a common practice **and strongly recommended** to write always a **constructor** of the class, even if it is an emty function. Important points about constructors:- The constructor is called automatically when a variable of that class type is defined, and can be used to initialize data members.- It has the same name as the class.- It doesnt have return statement.- A constructor without any arguments is called the **default constructor**, and should initialize all data members.- If there is not a constructor explicitly defined, the compiler will define it without any arguments and any statements.Let's add a constructor in the class we previously created:<jupyter_code>!gedit src/item_v3.h
!gedit src/item_v3.cpp
!gedit src/main_item_v3.cpp
!g++ -o item_v3.exe src/main_item_v3.cpp src/item_v3.cpp
!./item_v3.exe<jupyter_output><empty_output><jupyter_text>Constructor Overloading We saw in the last lesson that C++ is able to overload functions, i.e., have two functions with the same name but with different arguments. Same happens with the constructor. Is not mandatory, but sometimes is nice to give the user the chance to initialize the class members directly from the constructor. As an example, in our item class, we have created a default constructor that initializes all the member variables to a value. Similar things happen for classes that you have already used, like `vector` or `string`. ```c++std::string s; // Declares a string s, and initializes it to "" and with size 0.std::string s("something"); // Creates a string s, but when creating it, it also fills it with "something"```We want to do something similar with our class. In this case, we want to be able to initialize the class with values for price, name and number of items. Thus, we will overload the constructor to also have that option.<jupyter_code>!gedit src/item_v4.h
!gedit src/item_v4.cpp
!gedit src/main_item_v4.cpp
!g++ -o item_v4.exe src/main_item_v4.cpp src/item_v4.cpp
!./item_v4.exe<jupyter_output><empty_output><jupyter_text>Destructors When we create an object we need the constructors, either the default constructor or the overloaded one. In the constructor, or in some modifier functions, we migh perform memory allocations, that unless we free them, will yield memory errors. In this lesson is not crutial to talk about them, but is always a good practice to add the **destructors** in your classes. - The destructors are defines always by the class name preceeded by `~`.- They should free all the memory and make sure there is not a single bit allocated after the call to the destructor.In our Item class, since we don't need any statement in the destructor, we would not deed to explicitly write it. However, **it is good practice to ALWAYS write a destructor, even if is an empty function**. Let's add the destructor to our Item class. In the constructors and destructors, there is a print statement that will help us see when that is called.<jupyter_code>!gedit src/item_v5.h
!gedit src/item_v5.cpp
!gedit src/main_item_v5.cpp
!g++ -o item_v5.exe src/main_item_v5.cpp src/item_v5.cpp
!./item_v5.exe<jupyter_output><empty_output><jupyter_text>Operator Overloading It will happen that sometimes we need to "add", "multiply", or compare classes. The standart operators `+`,`-`,`*`,`==`,... are defined for the default variable types, but not for the user defined classes. A solution is to write the actual definition of the operator, known as **operator overloading**. The following code contains a class that has two double numbers for feet and inches. We can define an addition operator that will add the two variables:<jupyter_code>!gedit src/operator_overload_01.cpp
!g++ -o operator_overload_01 src/operator_overload_01.cpp
!./operator_overload_01<jupyter_output><empty_output><jupyter_text>As an example, overload the operators `` so the main function passes the assertions. Do not modify the main function!<jupyter_code>!gedit src/operator_overload_02.cpp
!g++ -o operator_overload_02_sol src/operator_overload_02_sol.cpp
!g++ -o operator_overload_02 src/operator_overload_02.cpp
print("Your answer:")
!./operator_overload_02
print("\nSolution:")
!./operator_overload_02_sol<jupyter_output><empty_output><jupyter_text>Problems  Problem 1 Create a molecule class, and without modifying the `main.cpp` file (just uncomment the statements once your class is ready), make it compile and pass the assertions. The molecule class should have the following public member functions:- Default constructor clearing the vectors, and setting number of atoms to -1- Overloaded constructor that creates the molecule passing as argument **ONLY** the XYZ vector (arg1) and the atom names vector (arg2)- Destructor- Function that sets/gets the xyz (given a vector of double) (Set/GetXyx)- Function that sets/gets the atom names (given a vector of strings) (Set/GetAtNames)- Function that sets/gets the number of atoms in the molecule (Set/GetNumAts)And the following private member variables- A double vector with the coordinates- A string vector with the atom names- An integer with the number of atomsEdit the `molecule.cpp` and `molecule.h` to implement your class, and then uncomment all the commented statements in `main.cpp`<jupyter_code>!gedit src/problem_01/molecule.cpp
!gedit src/problem_01/molecule.h
!gedit src/problem_01/main.cpp
!g++ -std=c++11 -o main.exe src/problem_01/main.cpp src/problem_01/molecule.cpp
!g++ -std=c++11 -o main_sol.exe src/problem_01_sol/main_sol.cpp src/problem_01_sol/molecule_sol.cpp
print("Your answer:")
!./main.exe
print("\nSolution")
!./main_sol.exe<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07852412488174078, 'fraction_numerical': 0.00804162724692526, 'mean_word_length': 4.876042245692052, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '325767', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2921, 'n_tokens_neox': 2815, 'n_words': 1434, 'path': 'lessons/06-objects/L06_objects.ipynb', 'repo_name': 'chemphys/LearnCPP', 'size': '10570'}