Access private variable in global scope - c++

In this below code, the foo function in the global scope tries to access the private variables of a Box, which ofcourse doesn't work. I have to make the foo function work with one line of code at the place show code for a school assignment.
#include <iostream>
using namespace std;
class Box {
int x,y;
public:
Box(int xi,int yi) {x=xi;y=yi;}
// One line of code to make foo(Box, Box) work
};
bool foo(Box l,Box r) {return (l.x*l.y)>(r.x*r.y);}
int main(int argc, char* argv[]) {
Box b1(3,4),b2(1,2);
if (foo(b1,b2)) cout << "b1>b2\n";
return cin.get();
}

Look into the friend keyword.

First off, this is not a priori a dirty thing. The placement of the comment line already indicates that the class Box controls who is allowed to touch its privates (pun intended).
Secondly, since this is a school assignment I think that the solution should have been mentioned in class: this can be achieved using a friend declaration.

Declare foo as a friend function inside Box
#include<iostream>
class Box {
int x,y;
public:
Box(int xi,int yi) :x(xi),y(yi){}// Always use initializer list for initializing data members, i.e. prefer initialization over assignment
friend bool foo(Box,Box);// friend functions can access private members
};
bool foo(Box l,Box r) // friend keyword not to be written while defining the function
{return (l.x*l.y)>(r.x*r.y);}
int main(int argc, char* argv[]) {
Box b1(3,4),b2(1,2);
if (foo(b1,b2)) std::cout << "b1>b2\n";
return std::cin.get();
}

In addition to the other answers involving friends, a better answer for the long term (although not a one-line change) would be for Box to overload the appropriate comparison operators.

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.

How to use a common friend function to exchange the private values of two classes

I copy this program in my book.But i not understand one line in this program.This line is
friend void exchange(class_1 &,class_2 &);
My question is why use & operator in bracket? Please explain.
#include <iostream>
using namespace std;
class class_2;
class class_1{
int valuel;
public:
void indata(int a){valuel=a;}
void display (void){cout<<valuel<<"\n";}
friend void exchange (class_1&, class_2&);
};
class class_2{
int valuel_2;
public:
void indata(int a){valuel_2=a;}
void display (void){cout<<valuel_2<<"\n";}
friend void exchange (class_1&, class_2&);
};
void exchange (class_1 &x,class_2 &y){
int temp=x.valuel;
x.valuel=y.valuel_2;
y.valuel_2=temp;
}
int main()
{
class_1 c1;
class_2 c2;
c1.indata(100);
c2.indata(200);
cout <<"values before exchange"<<"\n";
c1.display();
c2.display();
exchange(c1,c2);
cout <<"values after exchange"<<"\n";
c1.display();
c2.display();
return 0;
}
"&" means that the two arguments are references. See What are the differences between a pointer variable and a reference variable in C++? for more info.
By passing the values by reference, your exchange method will be able to modify the objects in memory. Try without the & and see what happens! Your exchange() method will instead take copies of the object you pass in, but not actually modify the data as it's stored in memory; in other words, the changes that occur when leaving off the & are local to that method, since the method is getting a copy and not the reference to the memory location of that object!

Define constructor of a class inside a namespace

I am fairly new to C++ so this may be an easy one.
I created a namespace and inside that namespace is a class. I cannot figure out how to define any of my class's constructors without receiving errors.
#include <iostream>
namespace bill {
const char * null ="EMPTY";
const int MAX_STACK_SIZE = 100;
class myStackClass {
private:
int i;
public:
myStackClass();
myStackClass(int[], int);
int peek();
int pop();
int push(int insertMe);
const char empty[5];
};
}
using namespace bill;
bill::myStackClass::myStackClass() //bill::myStackClass() doesn't work either
:
i(0)
{ //error C2448: 'i' : function-style initializer appears to be a function definition
} //"bill::myStackClass::myStackClass()" provides no initializer for:
const member "bill::myStackClass::empty"
bill::myStackClass::myStackClass(int[],int)
{ //error C2439: 'bill::myStackClass::empty' : member could not be initialized
} //"bill::myStackClass::myStackClass(int *, int)" provides no initializer for:
const member "bill::myStackClass::empty"
int bill::myStackClass::peek() // I am able to call methods belonging to the class
{
}
I'm sorry if any of this information is cluttered and hard to read or just downright not helpful. I have been reading my textbook and googling errors for hours and would really appreciate some insight. Thank you.
It's a bit difficult to decipher what you're looking for, as your stack class isn't much of a stack. That said, just to get it to compile without warnings, you have to initialize your empty class member in the constructor initializer list, as you've declared it to be const.
e.g. if you have your constructors as:
bill::myStackClass::myStackClass()
: i(0), empty {}
{}
bill::myStackClass::myStackClass(int[],int)
: empty{}
{}
This will initialize your empty char array to be, well, empty. If you wanted it to contain something, then you could specify it in within the curly brackets, e.g.
bill::myStackClass::myStackClass()
: i(0), empty {'H', 'E', 'L', 'L', 'O'}
{
std::cout << empty << std::endl;
}
then creating an object of your class (via the no-arg constructor) will print HELLO
bill::myStackClass stk; //--> prints HELLO
I should also make note that the use of uniform initializers (the curly-braces) is a C++11 feature, so depending on your compiler, you might have to supply an extra flag (i.e. -std=c++11)
You don't need to say using namespace bill if you are already pre-pending bill:: to your method definitions (which in your posted code, you are). The using namespace bill makes it such that the bill namespace is searched when resolving your identifier names, but if you're explicitly stating them to be bill within the bill namespace (via the bill::), then this isn't needed.
Also, the default scoping for a class if private, so it's redundant to specify the first part of a classes members to be private like that.

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

Trouble with friend in C++

Ah yes "friend" the most dreaded of keywords, not quite object oriented, not quite procedural. Well here it is making trouble again, I have every possible warning I could think of on, and all the GCC can tell me is that read poly() is not declared in this scope (main.cpp). Can anyone help me figure out what I'm doing wrong? I've tried rearranging the code in read poly, but that doesn't help, no other function prototypes seem to change this behaviour either. I just know I'm going to be hitting myself when I figure out what it is.
//main.cpp
#include "Polynomial.h"
int main()
{
Polynomial test = readPoly();
}
//Polynomial.h
class Polynomial
{
public :
/** creates the zero Polynomial and sets the default output character*/
Polynomial();
/** creates the constant Polynomial c */
Polynomial( int c );
/** creates a Polynomial with one term c*x^d */
Polynomial(int c, int d);
Polynomial(const Polynomial& toCopy);
friend const Polynomial readPoly();
void insert(Term* term);
}
//Polynomial.cpp
const Polynomial readPoly()
{
cout << "How many terms? ";
int termQty = 0;
cin >> termQty;
int coefficient,degree;
Polynomial newPoly;
for (int n = 0; n <= termQty; n++)
{
cin >> coefficient >> degree;
newPoly.insert(new Term(coefficient,degree));
newPoly.degreeCached = max(degree, newPoly.degreeCached);
}
return newPoly;
}
A friend declaration declares a function to exist in the nearest
enclosing namespace scope, but it only makes the declaration visible
within the class or through ADL. And since the function doesn't have
any arguments which use Polynomial, ADL won't find it. Just add a
declaration of the function in the surrounding namespace scope. Or make
it a static member, rather than a friend—in this case, it seems
more appropriate (to me, at least). In that case, you would call it
with Polynomial::readPoly() (or just Polynomial::read(), since the
scope resolution says explicitly what we are reading). Such static
members are probably the most usual implementation of the factory
function idiom.
Looks like you haven't declared readPoly() before using it. You can re-arrange the source (some more) so that it appears above main() or better still declare it before use:
//Polynomial.h
class Polynomial
{
....
};
extern const Polynomial readPoly();
readPoly indeed is not declared in this scope. Add a function declaration in the header. The friend clause only tells that this function can access private members, but it does not declare the function itself. So in the main the function is really not declared.