Need of :: to specify class for functions but not variables? - c++

Why do I need to use :: to denote if a function is a member function but I don't need to do it for the instance variables? I do understand that :: is used to differentiate between standalone and member functions, but I still don't get the variables part. I'll give an example of what I'm talking about.
Shape.h
# pragma once
class Shape {
private:
int height;
int width;
public:
Shape(int height, int width);
int getHeight();
int getWidth();
}
Shape.cpp
#include "Shape.hpp"
Shape::Shape(int height, int width) {
this->height = height;
this->width = width;
}
int Shape::getHeight() {
return height;
}
int Shape::getWidth() {
return width;
}
Here, I have to to specify the class of the Shape constructor and the getters in order for the compiler to know what I'm talking about. So how come when I do return height; or this->height without specifying class it understands what I'm talking about.

C++ uses a model where it initially assumes everything is in the same namespace/class as what it's declared in unless stated otherwise. So, for example, if you write
int getHeight() {
return height;
}
at the top level of a C++ file, the compiler assumes you're declaring something in the global namespace. That means that getHeight is a free function. Then, the statement return height; is interpreted in the context of a free function in the global namespace - it'll start searching local variables for height, then global variables in the global namespace.
On the other hand, if you write
int Shape::getHeight() {
return height;
}
you're explicitly telling C++ "hey, I know that this code is in the global namespace at the top level, but I'm explicitly indicating that this is actually inside of the Shape class." At that point, the compiler says "ah, gotcha, you're inside Shape now" and interprets the code that's written as though it were inside Shape. In that sense, the statement return height; first starts looking for a local variable named height, then looks for a data member of Shape named height, then looks for global variables named height.
There's no fundamental reason why C++ had to do things this way, but there is a nice internal consistency to it. You stay at whatever "scope level" a statement or definition appears unless something explicitly moves you into a different scope level. So once you've declared the function in a way that says it's in Shape, everything inside it evaluates relative to Shape rather than to the global namespace.
Hope this helps!

but not variable. this is not true, you have to use :: if you want to get value outside the scope of the A class.
class A {
public:
const static int a = 5;
A (){}
};
int main (void) {
std::cout << A::a;
}

Related

How does Data Encapsulation actually happen in OOP?

I'm learning C++.
Came across data encapsulation and data hiding at a website, check out the following piece of code:
#include<iostream.h>
#include<conio.h>
class sum {
private: int a, b, c;
public:
void add() {
clrscr();
cout << "Enter any two numbers: ";
cin >> a >> b;
c = a + b;
cout << "Sum: " << c;
}
};
void main() {
sum s;
s.add();
getch();
}
NOW. As it says here that:
The main advantage of using of encapsulation is to secure the data from other methods, when we make a data private then these data only use within the class, but these data not accessible outside the class.
What happens underneath the code, what does the compiler do that makes it inaccessible to other classes? And in the given example what was the reason behind defining a,b and c as private.
What were they trying to achieve by hiding "just the declarations of the three variables"? Because anyone can see that inside public three numbers being used are a,b, and c - first two for input and third one for output.
How is this possible that the data under private can't be accessed
outside the class?
Compiler makes sure you don't. If you try to access say a outside class, your code will not compile.
And in the given example what was the reason behind defining a,b and c
as private.
It could be anything! But as a result, a,b and c are not accessible outside members of class.
Basically you want to hide some variables in your class for the sake of consistency. So that you or your clients can not produce a code that makes unwanted and uncontrolled changes.
Updates:
What happens underneath the code, what does the compiler do that makes
it unaccessible to other classes?
Compiler implementation check for access level while producing code. If there is something wrong, you will get a syntax error and no machine code will be generated from your file.
And in the given example what was the reason behind defining a,b and c
as private; what were they trying to achieve by hiding "just the
declarations of the three variables"? Because anyone can see that
inside public three numbers being used are a,b, and c - first two for
input and third one for output.
You don't hide variables in your class to make them invisible to others. Private variables that are not intended to be used from outside of the class can be marked as private to limit the potential for coding errors.
As an example consider following class:
class rectangle {
public:
int width;
int height;
int area;
};
void something_important(const rectangle& r) {
// ...
}
What happens if I pass a rectangle of width -10, height 0 and area of -15? There could be a plane crash or a nuclear weapon launched to some wrong target... So I will make sure my rectangles are always valid:
class rectangle {
public:
void set_width(int w) {
if(w) width = w;
else width = 0;
area = width*height;
}
int get_width() const {return width;}
void set_height(int h) {
if(w) height = h;
else height = 0;
area = width*height;
}
int get_height() const {return height;}
int get_area() const {return area;}
private:
int width;
int height;
int area;
};
So no one can make a rectangle of negative height or width, and no one can make a rectangle having a wrong area. (you can not actually change area directly)
I hope it makes sense for you now.
What happens underneath the code, what does the compiler do that makes it unaccessible to other classes?
Not much. The compiler doesn't protect against access to the data. It protects against access to the name of the data. For instance:
void foo(class bar&, int&);
class bar {
int i = 0;
public:
void baz() {
foo(*this, i);
}
};
void foo(class bar& b, int& i) {
//b.i = 42; // This is an error. b.i is private
i = 42; // This is okay, no matter what the local i refers to
}
In the example above, foo() cannot access b.i by name, because it's a private data member. But it can still modify it if it obtains a reference by other means. The member function baz() which has access to that name, binds it to the reference that foo() accepts. Thus allowing for its modification from outside the class's scope.

Could you make this code more ideal using 'this' as many times as possible?

class Location
{
int width, height;
public:
Location(){width = height = 0;}
Location(int w, int h)
{width = w; height =h;}
void show();
};
void Location::show()
{
cout << width << height << endl;
}
The problem wants me to fix the code and make it more ideal using this.
But I don't know how to use this neither do I know how can using this make the code more ideal. It may seem a pretty dumb question to ask, but I'm still quite new at all these... can anyone help me understand this?
You use this in this context to refer to the class member data. This means that you can change your constructor's parameter names to match the data members:
Location(int width, int height)
{
this->width = width;
this->height = height;
}
The function parameter names with and height have a closer scope than the class data members so this is used to refer to the latter.

scope of class variable defined in a function in C++

Consider the following C++ code:
// friend functions
#include <iostream>
using namespace std;
class CRectangle {
int width, height;
public:
void set_values (int, int);
int area () {return (width * height);}
friend CRectangle duplicate (CRectangle);
};
void CRectangle::set_values (int a, int b) {
width = a;
height = b;
}
CRectangle duplicate (CRectangle rectparam)
{
CRectangle rectres; // Defined without using new keyword. This means scope of this variable of in this function, right ?
rectres.width = rectparam.width*2;
rectres.height = rectparam.height*2;
return (rectres);
}
int main () {
CRectangle rect, rectb;
rect.set_values (2,3);
rectb = duplicate (rect);
cout << rectb.area();
return 0;
}
The variable "CRectangle rectres" is defined in the function "CRectangle duplicate".
Does this mean that the scope of the variable "CRectangle rectres" is limited to the function only ? (since it has been defined without using new keyword)
If answer to above question is yes, then how can it be returned (since it is a local variable) ?
Credits : Code take from : http://www.cplusplus.com/doc/tutorial/inheritance/
Your question as to 1 & 2 has been adequately answered by Patrick, but I thought I could expand a bit:
The way MOST compilers work [1] when you return a struct or class object is that the calling function passes in a pointer argument (that is hidden from view) for the "return here" value. So the called function will copy the result into the place supplied by the calling code - the actual copy is done by the copy constructor of the class.
note 1: that the C++ standard doesn't say how the compiler should do this, and if the compiler can produce magical code that just moves the bits by using "The Force" from Star Wars then that is also allowed according to the standard.
Yes, it is a local variable.
If you return a copy of rectres

Handling lots of variable declarations

I am implementing a class and I have a function that does things using lots of variables that need to be declared and initialised.
I'd like the variable declarations not to clutter the function and do something like:
doFunction(){
declare();
//Do things with variables declared in declare()
}
void declare(){
//declare lots of variables here
}
This does not work as the variables are scoped to declare() and aren't seen by doFunction(). What's a sensible way to handle this problem?
Since each of the variables that you declare must be assigned a value, you should combine declaration with initialization. In other words, instead of
int x;
double y;
std::string z;
x = 1;
y = 2.0;
z = "3";
do this:
int x = 1;
double y = 2.0;
std::string z("3");
This is pretty much as far as you can push this approach with locals: declaring variables is an essential part of the function body, you cannot (and arguably, should not) move it to a remote location.
You can also move the member function into a nested private class, move the local variables into the class, and do calculations there:
class specialCalc {
int x;
double y;
std::string z;
specialCalc() : x(1), y(2.0), z("3") {}
public:
int calculate() {
...
}
};
void doFunction() {
specialCalc calc;
cout << calc.calculate() << endl;
}
PS: I am deliberately not mentioning preprocessor-based solutions because they would negatively impact readability.
I'm not really advocating this, but:
struct Declare
{
int x;
float y;
char z;
vars() :x(1),y(3.14),z('z') {}
};
void doFunction()
{
Declare vars;
// use vars.x, vars.y and vars.z as your variables
}
You have a number of choices:
1) Get over it. If you need lots of variables, you'll need to suffer the fact they need to be declared somewhere.
2) Put them into a class or in a structure as a member variable so you can declare them in the .h file and they'll be invisible in the .C/.cpp file.
3) Aggregate them into an array, and declare only the array and initialize them in a for() loop or something. This really only works if they're all a similar type and you don't do silly things like "index 4" is my "counter object for this", and "index 5" is my "thing I'm going to print to the screen" as then you loose the name associated with the variable itself, which is rather helpful when reading the code later (of course).
4) put them in a define statement somewhere else:
#define MYVARS int a; char b[1024]; ...
void funstuff() {
MYVARS
}
5) Modify an IDE so that it can hide/collapse the variable declarations when you're viewing the code.
Note that of all of these choices, number 1 is still probably the right answer :-)

class members and functions c++

I'm learning c++. I have written a small program which should compute the energy
of a N particle system. Up to now I have three small files:
data.h:
class Particle {
public:
double mass;
double charge;
double posx,posy,posz;
};
Particle part[2];
main.cpp:
#include <iostream>
#include "data.h"
using namespace std;
double energy(Particle part );
int main ()
{
double sd;
part[0].mass = 10.0;
part[4].mass = 90.0;
cout << part[0].mass << "\n";
cout << part[4].mass << "\n";
sd = energy(part);
cout << "sd" << sd << "\n" ;
return 0;
}
energy.cpp:
#include <iostream>
using namespace std;
double energy(Particle part)
{
cout << part[0].mass << "\n";
double dummy;
dummy = 2.0;
return (dummy);
}
I have two questions:
1)I want to make visible the Class particle in the function "energy". In other words,
I want to use the variables of the class function (with the values given in "main")
in the energy function.
I have tried as you see energy(Particle part) but it seems Particle is not defined
in that scope.
2)As you see in "data.h" I declared "part" as an array with two members. However,
in "main" I can use more than two members, for instance part[3],part[4]... Why I
could use more members than those I declared?
I am compiling with g++ -o test energy.cpp main.cpp
thanks.
1)I want to make visible the Class particle in the function "energy". In other words, I want to use the variables of the class function (with the values given in "main") in the energy function. I have tried as you see energy(Particle part) but it seems Particle is not defined in that scope.
If I understand you right.. You want to have
Particle part[2];
to be use able in main.cpp and in energy.cpp ?
If yes.. change this to:
extern Particle part[2];
and in energy.cpp add this:
#include "data.h"
Particle part[2];
and you will be able to use
double energy()
{
//main.cpp will have same part
cout << part[0].mass << "\n";
double dummy;
dummy = 2.0;
return (dummy);
}
2)As you see in "data.h" I declared "part" as an array with two members. However, in "main" I can use more than two members, for instance part[3],part[4]... Why I could use more members than those I declared?
Because it's C/C++ ? no range checks. You can do what ever you want.
But if you do, the result will be unexpected.
1)I want to make visible the Class particle in the function "energy".
You should #include "data.h" in the file energy.cpp.
2)As you see in "data.h" I declared "part" as an array with two members.
You probably shouldn't have done that, for two reasons:
You will learn later to avoid declaring global objects. It is legal (and often correct) to do so, but until you learn, you probably want to declare it as a local variable in main.
You should not declare global objects in header files, since they will then be declared in every translation unit that includes the header file.
However, in "main" I can use more than two members, for instance part[3],part[4]... Why I could use more members than those I declared?
By indexing beyond the end of the array, you have invoked "undefined behavior". The system is free to do almost anything (for example, crash, send Bill Gates an email, start a global thermo-nuclear war, &c). Among the infinite variety of things included in "undefined behavior" is the most confusing one of all -- appear to work. That is what happened in your case. You should not count on it continuing to appear to work.
All sorts of things you can do with a class ...
struct Vector3
{
double m_x, m_y, m_z;
};
class Particle
{
public:
double ComputeEnergy() { // return answer }
double GetMass() const { return m_mass; }
double GetCharge() const { return m_charge; }
const Vector3& GetPos() const { return m_pos; }
void SetMass(double mass) { m_mass = mass; }
void SetCharge(double charge) { m_charge = charge; }
void SetPos(const Vector3& pos) { m_pos = pos; }
void SetPos(double x, double y, double z)
{
m_pos.m_x = x;
m_pos.m_y = y;
m_pos.m_z = z;
}
private:
double m_mass;
double m_charge;
Vector3 m_pos;
};
You need to #include "data.h" in energy.cpp. Includes are only processed on a per-file basis, so energy.cpp can't see the header without that.
EDIT: In your function, the parameter part, out-scopes the global definition of part, so the part in your function is not an array. You want:
cout << part.mass << "\n";
1>Include "data.h" in energy.cpp
2> C++ array is very primitive it doesn't has any bound checking so you were able to access part[4].But there is no guarantee that it will work every time.Most of the time program may crash during run-time complaining the memory is corrupt.
To answer the first question, you could simply include data.h in energy.cpp.
#include "data.h"
Unfortunately, you've created "part" in the global space and so each .cpp file will independently create it. When it goes to link the object files, it will see that multiple references to "part" exist. What you can do here is use the "extern" keyword and in data.h, you would simply declare it as an external variable. Or, because you only reference "part" in main.cpp, you could just move the global definition in there and the problem is solved.
Now, when it comes to what you have done in energy.cpp, you've create a separate variable also called "part". When scoping rules are applied, it means that the compiler is going to take the local definition over the global definition. Since you are passing a class object and not a class array, you'll get a compiler error when referencing it like "part[0].mass".
Instead, why are you concerned about the value of the other particle and not the particle you passed in? If you want the mass of a particular Particle object, then you should write it like "part.mass"
Of course, I would argue that what you really want to create is a member function for energy within Particle. Right now, you are currently using classes in a C style struct way. This means that you are missing the ability to use all the object oriented goodness that C++ has to offer. You could do it like this
class Particle
{
protected:
double mass;
double charge;
double posx,posy,posz;
public:
void SetMass(double newMass) { mass = newMass; }
void SetCharge(double newCharge) { charge = newCharge; }
void SetX(double newX) { posX = newX; }
void SetY(double newY) { posY = newY; }
void SetZ(double newZ) { posZ = newZ; }
double GetEnergy() { return 2.0; }
};
To answer your second question, C++ assumes you know more about the memory then it does. There is no bounds checking in GCC(AFAIK) because the memory could be allocated anywhere at any time and deallocated as well. However, unlike other languages, you have to manage the memory yourself. There's a lot of optimizations and C++ trickery that this enables(like declaring a zero sized array for unknown sizes and assigning a block of memory to it).
Cheers!