public / private
Encapsulation
Putting the class in a file .h and .cpp
example 1
example 2
Constructor (
Overloading the constructor
Destructor
Constant methods
Example source code used in BeagleBoard-Xm project
Association between classes
Mutator methods
Operator overloading
Polymorphism
#ifndef
Compiling a Class
References
Classes are an expanded concept of data structures: like data structures, they can contain data members, but they can also contain functions as members.
Classes allow to hide complex code, and make it easy to the code be used by third parties.
class Personnage // minimum to create a class
{
} ;
– it is a good practice that the name of the class start always by an upper case.
– In object-oriented programming (OOP), an object is an instance of a specific class.
– variables inside a class are called members.
– functions inside a class are called methods.
– A special code, UML, has been created to modeling classes before starting to make the code.
– It is a good practice to start names of members class by m_ , like m_name.
public / private
public
– members or methods can be accessed from ouside of the class.
private
– members or methods cannot be accessed from ouside of the class.
by default, all elements of a class are private.
If you want for example that a function could be used from anybody from outside the class, you need to make your function public.
All that follow the code public: is public, and all that follows the code private: is private.
Methods can change the value of members, because the methods are part of the class,
that is where it should be done ( members are usually private )
Encapsulation
All members of a class should always be private… if your assign them as public, it make sure programs really easy to mess up…
I don´t want to enter for now in software engineering development details…you will catch it with practice.
Putting the class in a file .h and .cpp
For better organisation, you should create two new files to put your class, .h and .cpp.
You don´t have to do this way, you could put all in a single file, or even several classes in one single file….
Put in a header file .h the members and the prototypes of the class.
A file .cpp will have definition and implementation of the methods.
In .h file, it is recommended to never use namespace std, use std::string.
In most of IDE´s, we can create a Class in the up toolbar : File -> New -> Class, and it will be added two Template files, .cpp and .h in our project.
why separating a Class in to files .h and .cpp ?
If you want to distribute your class to friends to use or even sale it, you gonna wanna compile the .cpp file and change all in 1´s and 0 ´s,
and you will give the .h code where there is the prototypes to the programmers, but they won´t be able to change the functions itself.
in the main file, you will only hate to #include”file.h”
example 1 :
#include <iostream>
using namespace std;
class MyClass {
public:
void coolSaying () {
cout<<“my white table is outside”<<endl;
}
};
int main()
{
MyClass myObject ;
myObject.coolSaying () ;
return 0 ;
}
example 2 :
// instead of directly accessing private variables, we use public functions
#include<iostream>
using namespace std;
class MyClass {
public:
void setName (string x) {
name = x ;
}
string getName () {
return name;
}
private:
string name;
};
int main ()
{
MyClass My;
My.setName (“Jose”);
cout << My.getName() << endl ;
return 0 ;
}
Constructor
A contructor is by default created by the compiler, this one is empty ;
But we need most of time to create one that replace the empty default constructor;
Constructor never have a return type ;
The principal function of the constructor is to initialize the members;
The members are declared in the .h file, but they are not initialized there, this is the function of the constructor;
The constructor is essential to initialize the members that are not objects ( int, double, char ,..) because these ones have unknown values;
Members that are String type, don´t need to be initialized;
The constructor is a particular method that should have the same name as the class name, and should return nothing, not even void;
that´s how your C++ program knows that it´s constructor, because once it comes across a function with the same name it knows that´s it is the constructor.
Constructor is a function that is is called automatically as soon as your create the object.
#include <iostream>
using namespace std ;
class MyClass {
public:
MyClass () {
cout << “this will be printed automatically()” << endl ;
}
};
int main ()
{
MyClass My ;
return 0 ;
}
#include<iostream>
using namespace std;
class MyClass {
public:
MyClass (stringz) {
setName(z);
}
void setName (string x) {
name=x;
}
string getName() {
return name;
}
private :
string name ;
} ;
int main()
{
MyClass My (” Lucky Lucky Jose”) ;
cout << My.getName () << endl ;
return 0;
}
Constructor Example : initializing the members value
Personnage::Personnage()
{
m_vie = 100;
m_mana = 100;
m_nomArme = “Épée rouillée”;
m_degatsArme = 10;
}
other way : initialization list
Personnage::Personnage() : m_vie(100), m_mana(100), m_nomArme(“Épée rouillée”), m_degatsArme(10)
{
}
another example :
Time::Time ( int hours , int minutes , int seconds ) : m_hours(hours) ,m_minutes(minutes), m_seconds(seconds)
{
}
in main.cpp
Time time1 (0,10,20) ;
Overloading the constructor
You overload a function name f by declaring more than one function with the name f in the same scope.
The declarations of f must differ from each other by the types and/or the number of arguments in the argument list.
in .h file :
Personnage() ;
Personnage (std::string nomArme, int degatsArme) ;
Destructor
it is the called method when our object is removed from the memory. Symbol ~is used :
Personnage::~Personnage()
{
}
Constant methods
keyword const is added at the end of the prototype and declaration method.
It means that we do not modify the object,ie, we do not change any value of its members.
Used in method that only return information.
//Prototype de la méthode (dans le .h) :
void myMethod ( int parameter ) const;
//Déclaration de la méthode (dans le .cpp) :
void MyClass::myMethod ( int parameter ) const
{
}
It allow to make a more secure code, and let the the user of the class to know that the class will not change the object.
We help the compiler to generate a binary code with better quality.
before go forward in classes, let´s see an example ….
Example source code used in BeagleBoard-Xm project
Gpio.h source code
#ifndef GPIO_H_
#define GPIO_H_
class Gpio
{
// members
private :
int port;
int status;
int fd;
volatile ulong *gpio;
// prototype of methods
public:
Gpio ();
void Gpo (int,int) ; // should put void Gpio::Gpo ( int Port , int Status ) to better define the method ?
int Gpi (int);
~ Gpio ();
} ;
#endif
Gpio.cpp source code
#include “Gpio.h”
// —————————————- Construtor ———————————————
Gpio::Gpio() {
// constructor, have to be the same name as the class name : Gpio
fd = open (“/dev/mem”, O_RDWR | O_SYNC);
if (fd < 0) printf (“Could not open memory\n”);
if (fd > 0) printf (“memory map open successfully, file descriptor : %d\n”,fd);
gpio = (ulong*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x49050000);
if (gpio == MAP_FAILED) {
printf (“Gpio Mapping failed\n”);
close (fd);
}
}
// —————————————- Gpo ———————————————
void Gpio::Gpo ( int Port , int Status )
{
port = Port;
status = Status ;
// GPIO5 : 32 bits , MSB 159………128 LSB
port = 0xFFFFFFFF & ( ~(1<< (Port-128))) ;
// Configure Port as ouptut
// bit=0 -> output bit=1 -> input
// GPIO_OE Output Enable Address Offset : 0x034
gpio[0x6034/4] = gpio[0x6034/4] & port ;
if ( status == 0 )
{
// GPIO DataOutput Address Offset : 0x03C
gpio[0x603C/4] = gpio[0x603C/4] & port ;
}
if ( status == 1 )
{
gpio[0x603C/4] = gpio[0x603C/4] | ~port ;
}
}
// —————————————- Gpi Method ———————————————
int Gpio::Gpi(int Port)
{
int input = 2 ;
port = Port;
// GPIO5 : 32 bits , MSB 159………128 LSB
// reset bit to enable GPIO pin / GPIO5
port = 0xFFFFFFFF & ( ~(1<< (Port-128))) ;
// Configure Port as input
// bit=0 -> output bit=1 -> input
// GPIO_OE Input Enable , Address Offset : 0x034
gpio[0x6034/4] = gpio[0x6034/4] | ~port ;
// GPIO DataInput Address Offset : 0x038
if ( (gpio[0x6038/4] = gpio[0x6038/4] & ~port) == 0 )
input = 0;
if ( (gpio[0x6038/4] = gpio[0x6038/4] & ~port) == (1<<(Port-128)) )
input = 1;
return (input);
}
// —————————————- Destrutor —————————————————–
Gpio::~Gpio()
{
close(fd);
}
main.cpp sample source code
#include “Gpio.h”
Gpio Led1 , Led2 ;
Gpio Input ;
……..
Led1.Gpo(138,0) ;
………
status = Input.Gpi(137) ;
Association between classes
it´s putting an object inside anothe object, or using an object by another object…
If we are changing an existing Class, we should not change the existing methods ( deleting, rename, …) because they could be already be used by someone else or by ourself in the main code and it would not be working anymore.
#include “Skills.h”
…
…
private:
int m_name ;
int m_years ;
Skills m_skills; // Skills is an object, defined by Skills.h and Skills.cpp files
…
…
Mutator methods
set , also known as setter method. Is a method used to control changes to a variable.
get , also known as accessor method. Should added keyword “const” . returns the value of the private variable.
int getAge() const ;
Operator overloading
base class : Mother.h
derived class : Daughter.h
Daughter Class can inherate everything from Mother Class, exept private variables
#ifndef DAUGHTER_H
#define DAUGHTER_H
class Daughter: public Mother // in the Daughter class, we include the Mother Class ( public and protected functions and members )
// Daughter Class does not inherate the private members of Mother Class ( they still private )
// Daughter class is inheriting from Mother Class
{
public:
Daughter();
};
#endif
Polymorphism
The word polymorphism means having many forms.
Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.
C++ polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function.
Is using the same function for different object, but having many different outcomes…depending of which object call the function.
#include <iostream>
using namespace std;
class Enemy {
protected:
int attackPower;
public:
void setAttackPower ( int a ) {
attackPower = a ;
}
};
//—————————————————
class Ninja: public Enemy {
public:
void attack () {
cout << “I am a Ninja, ninja chop! –” << attackPower << endl ;
}
};
//—————————————————
class Monster: public Enemy {
public:
void attack() {
cout << ” Monster must eat you !!! – ” << attackPower << endl;
}
};
//—————————————————
int main() {
Ninja n ;
Monster m ;
Enemy *enemy1 = &n ; // we can put the address equal to the pointer because n is a more specific type of enemy
// everything that an enemy can do, a ninja can do
Enemy *enemy2 = &m ; // everything that an enemy can do, a monster can do
enemy1->setAttackPower (29) ; //whenever you´re working with pointer function you need a narrow
enemy2->setAttackPower (99);
n.attack () ;
m.attack () ;
}
A class is made abstract by declaring at least one of its functions as pure virtual function.
A pure virtual function is specified by placing “= 0” in its declaration as follows:
virtual int getArea() = 0 ;
The purpose of an abstract class (often referred to as an ABC) is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface.
Thus, if a subclass of an ABC needs to be instantiated, it has to implement each of the virtual functions, which means that it supports the interface declared by the ABC. Failure to override a pure virtual function in a derived class, then attempting to instantiate objects of that class, is a compilation error.
Classes that can be used to instantiate objects are called concrete classes.
http://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm
#include <iostream>
using namespace std ;
//Baseclass
class Shape
{
public:
//pure virtual function providing interface framework.
virtualint getArea () = 0 ;
void setWidth ( int w )
{
width = w ;
}
void setHeight ( int h )
{
height = h ;
}
protected:
int width;
int height;
};
//—————————————————
//Derivedclasses
class Rectangle : public Shape
{
public:
int getArea ()
{
return ( width *height ) ;
}
};
//—————————————————
class Triangle : public Shape
{
public:
int getArea()
{
return ( width *height ) / 2 ;
}
};
//—————————————————
int main ( void )
{
Rectangle Rect ;
Triangle Tri;
Rect.setWidth (5);
Rect.setHeight (7);
//Print the area of the object.
cout << “Total Rectangle area:” << Rect.getArea () << endl ;
Tri.setWidth (5) ;
Tri.setHeight (7) ;
//Print the area of the object.
cout << ” Total Triangle area:” << Tri.getArea () << endl ;
return 0 ;
}
You can see how an abstract class defined an interface in terms of getArea() and two other classes implemented same function but with different algorithm to calculate the area specific to the shape.
#ifndef
Surround the definition files (.h) with ifndef to prevent re-inclusion
#ifndef DAUGHTER_H
#define DAUGHTER_H
your normal code here
#endif
Compiling a Class
to build an object file of which you want to link against other code later. This is done by compiling with the -c option.
g++ -c Class.cpp -o Class.o
By default g++ will compile and link the files you give it. -c tells it just to compile.
References
http://fr.openclassrooms.com/informatique/cours/programmez-avec-le-langage-c
http://stackoverflow.com/questions/751681/meaning-of-const-last-in-a-c-method-declaration
http://www.cplusplus.com/doc/tutorial/classes
Youtube :
thenewboston.org from buckys Roberts
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.