/PiscineCPP

42 PiscineCPP

Primary LanguageC++

42 C++ Piscine September 2022

Summary

A group of subject designed to learn CPP through differents exercices, here are some explanation about the specification of every modules.


Table of contents

  1. CPP00: Strings and I/O Manipulation
  2. CPP01: New, class, ...: basics
  3. CPP02: Operator overload
  4. CPP03: Inheritance : basics
  5. CPP04: Polymorphism
  6. CPP05: Exception, Try, Catch
  7. CPP06: cast, convert...
  8. CPP07: Template
  9. CPP08: Containers

CPP00:

Strings and I/O Manipulation

To write some text on STDOUT we use the '<<' operator to push a string into it.

std::cout << "Hello World!" << std::endl;

In C++ we have the class string, this class is defined in <string>.

#include <string>
#include <iostream>

int	main()
{
	std::string name;

	std::getline(std::cin, name);
	std::cout << "My name is: " << name << std::endl;
}

We can use std::cin to communicate through STDIN and write information to our code for example above with the function getline


CPP01:

New, class, ... : basics

Sometimes we want to use an object outside of the function that created it:

Cat	createCat(void)
{
	Cat	albert;

	return (albert);
}

int	main()
{
	Cat albert = createCat();
}

For example we can't do something like that because albert is destroyed when the function createCat() end, so we have to use the keyword new to create our Cat on the heap and not on the stack

Cat	*createCat(void)
{
	Cat	*albert = new Cat();

	return (albert);
}

int	main()
{
	Cat *albert = createCat();

	delete albert;
}

Never forget that you have to destroy every object instanciated with the keyword new by using delete

Cat	*createCat(void)
{
	Cat	*groupsOfCats = new Cat[10];

	return (groupsOfCats);
}

int	main()
{
	Cat *groupsOfCats = createCat();

	delete []groupsOfCats;
}

Use delete[] to destroy entire array of object without having to iterate through it


CPP02:

Operator overload

in C++ you can overload all the operator, for example i want a new class MyInt, it have one attribute int number and i want to change the comportement of the + operator

class MyInt 
{
	private:
		int number;

	public:
		MyInt	operator+(const &rhs)
		{
			return (this->number - rhs.number);
		}
};

int main()
{
	MyInt int1(43);
	MyInt int2(1);

	std::cout << int1 + int2 << std::endl
	// output: 42
}

now the + operator acts like the - operator. You can define in your class all the operator (>, <, <=, >=, !=, ==, >>, <<, =, [], *, ...)


CPP03:

Inheritance : basics

A class can inherit from another and share the same function and the same attributes

class Animals 
{
	protected:
		int		numOfLegs;
	
	public:
		void	getNumOfLegs() const;
		void	walk();
};

class Cat : public Animals 
{
	public:
		void	meow();

}
int main()
{
	Cat	felix();
	Animals	thing();

	felix.walk(); //Works!
	felix.getNumOfLegs(); //Works!
	thing.meow(); //Don't works!
}

CPP04:

Polymorphism

if a base class have a virtual function, this function can be overriden in the derived class

class Animals 
{
	protected:
		int		numOfLegs;
	
	public:
		void	getNumOfLegs() const;
		virtual void	walk() {
			std::cout << "i'm walking!" << std::endl;
		};
};

class Cat : public Animals 
{
	public:
		virtual void	walk() {
			std::cout << "i'm meowing" << std::endl;
		};
};

int main()
{
	Cat	felix();
	Animals	thing();

	felix.walk(); //"i'm meowing!"
	felix.getNumOfLegs(); //Works!
	thing.walk(); //"i'm walking"
}

if a class have a virtual methods equals to zero, this class is an interface, it can't be instanciated, it's just useful for inheritance

class Animals 
{
	protected:
		int		numOfLegs;
	
	public:
		void	getNumOfLegs() const;
		virtual void	walk() = 0;
};

class Cat : public Animals
{
	public:
		virtual void	walk()
		{
			std::cout << "i'm meowing" << std::endl;
		};
};

int main()
{
	Cat	felix();
	Animals	thing(); //DON'T WORK

}

Sometimes it's necessary to have the destructor in virtual if you delete an instance from a derived class through a pointer of a base class

class Base 
{
    // some virtual methods
};

class Derived : public Base
{
    ~Derived()
    {
        // Do some important cleanup
    }
};

int main() 
{
	Base *b = new Derived();
	// use b
	delete b; // Here's the problem! (undefined behavior)
}

Since Base's destructor is not virtual and b is a Base* pointing to a Derived object, delete b has undefined behaviour


CPP05:

Exception, Try, Catch

The try and catch keyword are very useful to spot and display error messages, here a little piece of code to explain the methods.

Nested class are an important part in creating exception, you define a nested class inheriting std::exception in order to throw error in your code.

class Test {
	public:
	//here is a nested class
		class ProblemsHere : public std::exception {
			public:
				virtual const char *what() const throw {
					return ("the custom message u want");
				}
		}

		void	doThing(std::string things);
}

void	Test::doThing(std::string things) {
	if (!things)
		throw ProblemsHere(); //throw an error, the name of the nested class
		//with parenthesis
	else
		return (things);
}


int main() {
	Test	obj;

	try {
		obj.doThing();
	} catch (std::exception &e) {
		std::cout << e.what() << std::endl;
	}

	//the execution continue here
}

with the keyword try we execute an instruction, if the instruction fail, we catch an std::exception &e and use the function what to display the custome message we want.

The executions of your code continue after the try and catch block.


CPP06:

cast, convert...

CPP07:

Template

CPP08:

Containers