C++ Learn: Object Oriented Programming
C++ Learn: Object Oriented Programming
The organization method/principle used in C++ is called Object Oriented Programming and it is based on the concept of
C++ classes.
Objects are the basic unit of oriented programming. They have both data and functions that operate as one item.
Classes are templates for objects, with its data and functions called class attributes and class methods. Objects will be
instances of a class.
C++ Classes
we've been using objects in the course, every time we needed the class RosbotClass we would create an object rosbot:
RosbotClass rosbot;
// Access specifiers of the class..here public. Everything indented below public can be accessed anywhere where the object
is visible.
// Other possibilities are private and protected.
// Good practice to declare attributes as private.
public:
void get_name() {
cout << “This hobbits name is ” << name << endl; // You can see attribute name used here
}
void convert_height_to_cm();
}
Hobbit first_hobbit;
first_hobbit.name = “Frodo”;
first_hobbit.age = 28;
first_hobbit.get_name();
1/6
Call object's functions
If we need to check the name of the hobbit we just set, we can use the class function get_name(). To call a method of a
class we just need to use again a dot and its name:
first_hobbit.get_name();
SCOPE OPERATOR ::
Once the class is defined, everytime we need to make use of some of its attributes or functions, we can call them as we
did with namespaces, using the scope operator ::
void Hobbit::convert_height_to_cm() {
height = height * 100;
cout << “Height of hobbit is ” << height << “centimeters” << endl;
}
first_hobbit.convert_height_to_cm();
In order to avoid that, a class can include a special function called its constructor, which is automatically called whenever
a new object of this class is created, allowing the class to initialize its attributes.
The constructor will have the exact same name as the class, and will be called below the public statement:
class Hobbit {
public:
Hobbit(); // Constructor declaration
Using constructor, we can pass parameters into it, as it is automatically called whenever a new object is created. We can
use it to directly set the values of the attributes.
class Hobbit {
public:
// Constructor declaration
void get_name() {
void converttocm();
int main() {
Hobbit first_hobbit("Frodo", 1.15, 28);
2/6
Hobbit second_hobbit("Sam", 1.26, 31);
We just created two objects of type Hobbit, with all their attributes set in just one line of code!! This is just powerful and
very clean!!!!!
ROSBOT CLASS
In this case we have separated the initialization of the class in another file, with all its attributes and methods. This file is
called a header file, with extension .h:
rosbot_class.h
Header file
#ifndef ROSBOT_CLASS_H
#define ROSBOT_CLASS_H
#include "geometry_msgs/Twist.h"
#include "nav_msgs/Odometry.h"
#include "sensor_msgs/LaserScan.h"
#include <list>
#include <ros/ros.h>
#include <string>
class RosbotClass {
private:
// Communicate with nodes
ros::NodeHandle n;
// Laser data
ros::Subscriber laser_sub;
std::vector<float> laser_range;
std::string laser_topic;
// Velocity data
ros::Publisher vel_pub;
geometry_msgs::Twist vel_msg;
std::string vel_topic;
// Odometry data
ros::Subscriber odom_sub;
std::string odom_topic;
float x_pos;
float y_pos;
float z_pos;
public:
RosbotClass();
void move();
void move_forward(int n_secs);
void move_backwards(int n_secs);
void turn(string clock, int n_secs);
void stop_moving();
float get_position(int param);
std::list<float> get_position_full();
double get_time();
float get_laser(int index);
float *get_laser_full();
};
----- Rosbotclass.cpp
#include "rosbot_control/rosbot_class.h"
#include "geometry_msgs/Twist.h"
3/6
#include "nav_msgs/Odometry.h"
#include "sensor_msgs/LaserScan.h"
#include "std_msgs/Float32.h"
#include "std_msgs/Int16.h"
#include "unistd.h"
#include <ros/ros.h>
#include <list>
#include <string>
// RosbotClass constructor
RosbotClass::RosbotClass() {
n = ros::NodeHandle("~");
laser_topic = "/scan";
laser_sub = n.subscribe(laser_topic, 10, &RosbotClass::laser_callback, this);
vel_topic = "/cmd_vel";
vel_pub = n.advertise<geometry_msgs::Twist>(n.resolveName(vel_topic), 1);
odom_topic = "/odom";
odom_sub = n.subscribe(odom_topic, 10, &RosbotClass::odom_callback, this);
ROS_INFO("Initializing node .................................");
usleep(2000000);
}
void RosbotClass::laser_callback(
const sensor_msgs::LaserScan::ConstPtr &laser_msg) {
laser_range = laser_msg->ranges;
// ROS_INFO("Laser value: %f", laser_range);
}
void RosbotClass::odom_callback(const nav_msgs::Odometry::ConstPtr &odom_msg) {
x_pos = odom_msg->pose.pose.position.x;
y_pos = odom_msg->pose.pose.position.y;
z_pos = odom_msg->pose.pose.position.z;
// ROS_INFO_STREAM("Odometry: x=" << x_pos << " y=" << y_pos << " z=" <<
// z_pos);
}
void RosbotClass::move() {
// Rate of publishing
ros::Rate rate(10);
4/6
ros::Rate rate(10);
double WZ = 0.0;
if (clock == "clockwise") {
ROS_INFO_STREAM("Turning clockwise..............");
WZ = -2.5;
} else if (clock == "counterclockwise") {
ROS_INFO_STREAM("Turning counterclockwiseeee ........... ");
WZ = 2.5;
}
void RosbotClass::stop_moving() {
ROS_INFO_STREAM("Stopping the robot ........... ");
vel_msg.linear.x = 0.0;
vel_msg.angular.z = 0.0;
vel_pub.publish(vel_msg);
}
list<float> RosbotClass::get_position_full() {
list<float> coordinates({this->x_pos, this->y_pos, this->z_pos});
return coordinates;
}
double RosbotClass::get_time() {
double secs = ros::Time::now().toSec();
return secs;
}
float *RosbotClass::get_laser_full() {
float *laser_range_pointer = laser_range.data();
return laser_range_pointer;
5/6
}
RosbotClass rosbot;
rosbot.move();
ROS_INFO_STREAM(coordinate);
return 0;
}
6/6