Showing posts with label const. Show all posts
Showing posts with label const. Show all posts

Get and Set Functions, Const and Object-Oriented Information Security

In this tutorial of our C++ course, we will use one more example of Class and Object, this time to better understand the use of setters and getters functions, as well as making our code more secure, through the keyword const.

Object-Oriented Get and Set Functions

Let's do another class example! Now we are going to work with a rectangle, which is different from the square that only has one side of equal value, the precise rectangle of the value of two sides. Let's call it length and width.

The function that takes the value of the area, let's call getArea() and the one that returns the perimeter value of getPerimeter() ... from get, which here means to get, access ...

As our variables are private, after all it is a security issue that no one from outside touches or sees them, we will need functions to set the value of these variables, they will be setLength() and setWidth() ... from set ...which means to define, to change.

See how our code looks:

#include <iostream>
using namespace std;

class Rect
{
    private:
        double length, width;

    public:
        double getArea();
        double getPerimeter();
        void setLength(double);
        void setWidth(double);
};

double Rect::getArea()
{
    return length * width;
}
double Rect::getPerimeter()
{
    return 2*(length+width);
}
void Rect::setLength(double l)
{
    length = l;
}
void Rect::setWidth(double w)
{
    width = w;
}

int main()
{
    Rect r;
    double var;

    cout<<"Length: ";
    cin >> var;
    r.setLength(var);

    cout<<"Width: ";
    cin >> var;
    r.setWidth(var);

    cout<<"Area: " << r.getArea() << endl;
    cout<<"Perimeter: " << r.getPerimeter() << endl;

    return 0;
}

In main(), we instantiate an object 'r' of type Rect, and declare a variable 'var' that will receive the values that the user will type, for the values of length and width.

First he types the value for the length, and we set that value using setLength().
Then he types the value for the width, and we set that value using setWidth().

Then just display the area and perimeter value, using getArea() and getPerimeter().

That is, we use getters and setters to access and change variables. Look again: no one in the outside world, not even the best hacker on the planet, will have direct access to these variables, only through the set and get functions.

Information Security with Object Orientation

"Well, we don't have access to variables directly, but we have through the functions of Set and Get, which is the same thing".

Well, almost, but there is a reason. You would still need to guess the name of these functions, to have access to them, but I do not disagree with you, this security has not yet been tested.

An example: a naughty hacker could very well set negative values for the sides of the rectangle, which is absurd! The sides of a rectangle must be positive!

That's where the magic of object orientation comes in! Let's change our setLength() and setWidth() functions, they will look like this:

void Rect::setLength(double l)
{
    while(l<=0){
        cout << "Negative length! Type a valid value: ";
        cin >> l;
    }
    length = l;
}
void Rect::setWidth(double w)
{
    while(w<=0){
        cout << "Negative widh! Type a valid value: ";
        cin >> w;
    }
    width = w;
}

Friends, as long as the value of l or w is negative, it will fall into the while and only leave that while when the value entered is greater than 0, and there is no chat, it may be the best hacker in the world, it will not circumvent it.

The keyword const in Object Orientation

As we said, the purpose of the getters functions is simply to take values, access this information, never, never, change it.

You can work in the treasury of a company and make the function getPaycheck() available to the rest of the company, for each one to see the salary amount ... but under no circumstances should these people be able to change the amount presented (in this case, the salary. ..imagine how wonderful it would be to be able to change your salary?)

One way to ensure that these functions are access only, is to use the keyword const, both in the header within the class definition and in the function declaration.

Now see how our code is complete, safe, beautiful and wonderful:

#include <iostream>
using namespace std;

class Rect
{
    private:
        double length, width;

    public:
        double getArea() const;
        double getPerimeter() const;
        void setLength(double);
        void setWidth(double);
};

double Rect::getArea() const
{
    return length * width;
}
double Rect::getPerimeter() const
{
    return 2*(length+width);
}
void Rect::setLength(double l)
{
    while(l<=0){
        cout << "Negative length! Type a valid value: ";
        cin >> l;
    }
    length = l;
}
void Rect::setWidth(double w)
{
    while(w<=0){
        cout << "Negative widh! Type a valid value: ";
        cin >> w;
    }
    width = w;
}
int main() { Rect r; double var; cout<<"Length: "; cin >> var; r.setLength(var); cout<<"Width: "; cin >> var; r.setWidth(var); cout<<"Area: " << r.getArea() << endl; cout<<"Perimeter: " << r.getPerimeter() << endl; return 0; }

Object Oriented Exercise

Increment the previous example. Make it also display the sides of the rectangle, to do this define and use the getLength() and getWidth() functions, use the const keyword to make these functions more secure and hacker-proof.

Comparison of Pointers and Pointer to Constants

In this tutorial, we will learn how to compare pointers as well as how to use constant variables with them.

Comparison between pointers in C++

In the same way that we can compare any two variables (such as int and double), we can also compare pointers.

And using the same operators:>,>=, <, <=, == and !=

We say, for example, that one pointer is greater than another, when, for example, its memory address in an array points to a variable whose index is greater than another.

For example:
int *ptr1 = array[0];
int *ptr2 = array[1];

So, the comparison: ptr2 > ptr1 will result in a true result.
ptr1 == ptr2 will result in a false result, as they point to different memory addresses.

That is, pointers are variables that store memory addresses.
So, when comparing two pointers, we are comparing two memory addresses, and not the values they point to, ok?

Pointers and C++ const

Whenever we use the keyword const, we are telling the compiler that the value stored in that variable should not be changed.

Often, we want to pass a variable as information for somewhere in code, but we don't want it to be modified in any way, in these cases, it is important to use the keyword const.

So far, we have used non-constant pointers that point to non-constant variables, that is, we can change up to the value of the variable via a pointer that points to it.

You cannot, for example, pass a pointer, which is not constant, to a function that expects a constant variable as an argument. Also, look:
#include <iostream>
using namespace std;

int main()
{
    const double pi = 3.14;
    const double *ptr = &pi;

    cout << *ptr << endl;

    return 0;
}
To point to a constant variable (pi), we had to define a constant pointer (const double *).
Try to remove the 'const' from the pointer declaration, and see what happens.

However, we can have a constant pointer that points to a variable that is not constant:
#include <iostream>
using namespace std;

int main()
{
    double pi = 3.14;
    double * const ptr = &pi;

    cout << *ptr << endl;

    return 0;
}
The difference is that this pointer will ALWAYS point to the same memory address. You can even change the value it points to. But he will never change the address it points to. Constant type pointers must be initialized when they are declared.

Finally, we can have a constant pointer, which points to a constant variable:
#include <iostream>
using namespace std;

int main()
{
    double pi = 3.14;
    const double *const ptr = &pi;

    cout << *ptr << endl;

    return 0;
}
Note that, in this case, we cannot change the address of the pointer (we cannot do ptr =&another_variable) nor can we change the value stored where the pointer points (*ptr = 21.12)

These cases of constant and pointers, as well as the comparison between pointers, are used a lot in the study of strings, for example.

Local, Global, Global Constant, and Static Variable

In this tutorial from our C++ e-book, we will learn a little more about the relationship between functions and variables, knowing the local, global, constant, and static variables types.

Local variable

When we declare a variable within a function, we say that it is local.
This is due to the fact that it 'exists' only for those who are within the function, that is, only inside can see it and its value.

Other commands in other functions cannot access it normally.
To illustrate this, let's declare the variable myVar with value 1, inside main().

Next, let's call the print () function, which will print the value of myVar:
#include <iostream>
using namespace std;

void print()
{
    cout<<myVar;
}

int main()
{
    int myVar=1;
    print();
    return 0;
}
This code is neither compiled, the error appears:
"'myVar’ was not declared in this scope | "

That is, the myVar variable is not within the scope of the print() function, it is as if it did not exist.

The opposite also applies:
#include <iostream>
using namespace std;

void print()
{
    int myVar=1;
}

int main()
{
    cout<<myVar;
    return 0;
}
That is, not even the main() function can see the internal content of the print() function.

Now let's declare myVar both inside print() and inside main(), and let's print both values:
#include <iostream>
using namespace std;

void print()
{
    int myVar=1;
    cout << "In print() = "<<myVar<<endl;
}

int main()
{
    int myVar=2;
    cout << "In main() = "<<myVar<<endl;
    imprime();
    return 0;
}
Results
C++ Progressive e-book

That is, we can declare variables of the same name, but in different functions.
And the functions only 'see' what's inside that function, ok?

Global variable

There is a way to make the same variable seen and accessed by several functions, just make it a global variable.

To do so, simply declare it outside the scope of functions.
For example, let's declare the variable pi, and store the value of pi.

Next, we will ask the radius value from the user, and using two other functions, we calculate the perimeter and the area of the circle:
#include <iostream>
using namespace std;
float pi = 3.14;

float perimeter(float r)
{
    return 2*pi*r;
}

float area(float r)
{
    return pi*r*r;
}

int main()
{
    float rad;

    cout<<"Radius: ";
    cin>>rad;

    cout<<"Perimeter: " << perimeter(rad)<<endl;
    cout<<"Area     : " << area(rad)<<endl;

    return 0;
}
Note that we use the pi variable in functions, without declaring them within their scope.

If we were to use local variables, we would have to declare pi more than once, which would not be very efficient.

Use global variables when they are needed in many different parts of your code.
And you can use the same name for a local and global variable. In this case, the local variable will have priority.

Global constants

Very careful when using global variables. In complex programs, it is easy to 'lose control' of global variables, as they can be changed anywhere in code.

In most cases, give priority to using same arguments.

However, if you want to use global variables that should not be changed, use the const keyword before declaring the variable:
  • const float pi = 3.14;

Let's suppose a hacker broke into your system, and entered a function called change(), which will change the value of pi to 4, sabotaging your project:
#include <iostream>
using namespace std;
const float pi = 3.14;

void change()
{
    pi = 4;
}

int main()
{
    change();

    return 0;
}
As the variable was declared with the const keyword, it will give the error:
"| 7 | error: assignment of read-only variable pi ’|"

That is, the variable is read only, cannot change the 'pi'. And in fact, no program should change pi, so it makes sense that it is global and constant, do you agree?

Let's assume that you will create a system for a large supermarket chain, and you will set the discount price at 10%, do:
  • const float off = 0.1;

Ready. Now thousands of functions can access the discount amount.
What if you want to increase the discount to 20%?
Easy, just do:
  • const float off = 0.2;

See that you changed just one thing, just one variable. But it automatically modified the calculations of the thousands of functions that use this variable directly.

It changes only once, and the change occurs in multiple corners.
If you had done it locally, you would have to go to each function and change variable by variable ... it would take hours or days.

But with constant global variable, no. Changes only once. And everything changes.
Did you get the utility of global and constant variables?

Static local variable

When we declare a variable within a function, it is created and reserved in computer memory at the beginning of the function and is destroyed at the end of the function's execution.

In the code example below, we initialize the myVar variable to 1, print, increment by one, and terminate the function.
#include <iostream>
using namespace std;

void test()
{
    int myVar=1;

    cout<<myVar<<endl;

    myVar++;
}

int main()
{
    test();
    test();

    return 0;
}
We call the test() function twice, and what appears on the screen is always the same: the value 1.

Each time the function runs, the variable is created, initialized and the value 1 is displayed. It is incremented, but then the function ends and the variable simply dies.

We then say that local variables are nonpersistent. That is, they do not 'persist', they are created and destroyed along with the function.

There is a way to make the variable persistent, that is, it is created initially and not destroyed, its address and value in memory still remains. These are the static variables.

To declare a variable to be static, just use the static keyword before the declaration:

  • static int myVar;


Veja:
#include <iostream>
using namespace std;

void test()
{
    static int myVar=1;

    cout<<myVar<<endl;

    myVar++;
}

int main()
{
    test();
    test();
    test();
    test();

    return 0;
}
Ready. No matter how many times you call the test() function, the myVar variable you will use is declared and initialized only once. When the function ends, it will still persist and when calling the function again, it will already take the previous value of the variable, to print and increment.

Like global variables, local static are always initialized to 0 if you do not explicitly initialize. And if you boot, this boot will only occur once, as you saw in the previous code example, ok?