Why is accessing private variable allowed here? - c++

I have this class declared. I observed that in the method distance(Point b), how is it possible to access the private members of Point - b.x and b.y? If I try to access b.x and b.y in main, it is not allowed.
#include <iostream>
#include <cmath>
using namespace std;
class Point {
private:
int x, y;
public:
Point() {
cout << "Constructor called" << endl;
x = 0; y = 0;
}
~Point() {
}
void set(int a, int b) {
x = a;
y = b;
}
void offset(int dx, int dy) {
x += dx;
y += dy;
}
void print() {
cout << "(" << x << "," << y << ")" << endl;
}
// HERE
double distance(Point b) {
return (sqrt(pow(x-b.x, 2)+pow(y-b.y, 2)));
}
};
int main() {
Point p, q;
p.print();
p.offset(4, 3);
p.print();
q.set(10, 2);
cout << "Distance: " << p.distance(q) << endl;
return 0;
}
NOTE: I have compiled and ran the program on ideone.com

The concept of access specifiers such as private, public etc. applies to classes, not just objects of classes. If a variable is private in a class, and an object A of that class has a function that takes another object B of the same class, A has access to B's private members since A and B belong to the same class.
Copy constructors rely on this:
#include <iostream>
using namespace std;
class A {
public:
A(){val = 1.0;}
//copy constructor
A(const A& _other) {
val = _other.val; //accessing private member of _other
}
double dist(A _a) {return val - _a.val;} //accessing private member of _other
private:
double val;
};
int main() {
A a;
A b;
cout << a.dist(b) << endl;
}

int x, y; are private to the Class Point. It means all the members of Class Point can access,modify it.
The functions and constuctors of Class Point are public i.e Other functions(from some other class etc) [like main] can access them. The idea of OOPS is to keep your data safe, Anyone who wants to modify the values can do it via the public methods of that class. They can't access them directly. This allows you to keep any check for invalid modifications to data [setting invalid values like height = -4; etc]
If u keep int x,y as public [which is not correct OOPs] any function (main etc) can access it and modify the value to something undesirable.
Point p;
p.x = -5 (suppose you only wanted +ve values for x , you can't check if the functions accessing is setting some undesirable value)`
Not a relevant analogy , but still...You have a room in the house which only the family members can access. Any outsider who wishes to keep or remove or do anything to the things in the house has to ask your family members to do it. If u assume even family members are not allowed to access the room [assuming even member functions can't access variables ] then there is no use of keeping anythin in the room [the data cannot be used by anyone]

Related

composition of classes in c++

This is an example of the composition of classes. But my code doesn't show a correct answer. This program must calculate the length of the line segment in the coordinates of the two ends of the line segment!
I don't know what to do in the main function. this code consists of two classes.
#include <cmath>
#include <iostream>
using namespace std;
class point {
private:
float x;
float y;
public:
void setpoint(float abscissa, float ordinate) {
x = abscissa;
y = ordinate;
}
float getx() { return x; }
float gety() { return y; }
};
class LineSegment {
public:
float length() {
result = sqrt(pow(a.getx() - b.getx(), 2) + pow(a.gety() - b.gety(), 2));
return result;
}
void displayMessage() { cout << result; }
private:
float result;
point a;
point b;
};
int main() {
point a;
float q, s;
cout << "Enter two numbers for first point:\n";
cin >> q >> s;
a.setpoint(q, s);
point b;
float e, r;
cout << "Enter two numbers for second point:\n";
cin >> e >> r;
a.getx();
a.gety();
LineSegment pt;
pt.length();
pt.displayMessage();
return 0;
}
enter image description here
The a and b local variables of your main() function are unrelated to the a and b members of class LineSegment. You should give LineSegment a constructor by which you can convey the endpoints to it, or at minimum provide a method or methods by which the endpoints can be set after the fact. You must not attempt to compute the segment length before its endpoints are set.
Neither the member a nor the member b are initialized for pt. You need to initialize them or they are initialized using the default constructor of point which happens to not do any initialization resulting in undefined behavior.
You could e.g. pass the points to the constructor of LineSegment to fix this:
class LineSegment {
public:
LineSegment(const point& p1, const point& p2)
: a(p1), b(p2)
{}
...
};
...
LineSegment pt {a, b};
...
Note: I recommend adding a prefix to member variables. m_ is one option (i.e. you'd use m_a and m_b as member variable names). This way you avoid confusion like this and also avoid shadowing of variables assuming this is the only kind of variable using this prefix.
Edit: You also never call setpoint on b in main; you need to do this before passing the points to the constructor in the above snippet.
Here is your code, touched up to work:
#include <cmath>
#include <iostream>
// using namespace std; // CHANGED: Bad practice
class point {
private:
float x = 0.0f; // CHANGED: Add default member initialization
float y = 0.0f;
public:
point() = default; // CHANGED: Add default constructor
point(int abscissa, int ordinate) : x(abscissa), y(ordinate) {} // ADDED
void setpoint(float abscissa, float ordinate) {
x = abscissa;
y = ordinate;
}
float getx() const { return x; } // CHANGED: Mark getters as const
float gety() const { return y; }
};
class LineSegment {
public:
// CHANGED: Add constructor so you can actually build a LineSegment
LineSegment(point one, point two) : a(one), b(two) {}
// CHANGED: Made a one-liner
float length() const {
return sqrt(pow(a.getx() - b.getx(), 2) + pow(a.gety() - b.gety(), 2));
}
// void displayMessage() const { std::cout << result; } // CHANGED: Not
// needed
private:
// float result; // CHANGED: Does not need to stored
point a;
point b;
};
int main() {
float q, s;
std::cout << "Enter two numbers for first point:\n";
std::cin >> q >> s;
point a(q, s); // Can now directly initialize
float e, r;
std::cout << "Enter two numbers for second point:\n";
std::cin >> e >> r;
point b(e, r); // CHANGED: Actually put values into b
// a.getx(); // CHANGED: These do nothing
// a.gety();
LineSegment pt(a, b); // CHANGED: Actually put data into pt
std::cout << "\nLine Length: " << pt.length() << '\n'; // CHANGED: Make use
// of functions now
// available
return 0;
}
Your biggest issues were not initializing your objects correctly. point b was never given the values e and r, and LineSegment pt was never given any points.
Making those small changes and your code works as expected. Just using a simple example of (0, 0) and (1, 1) provides output of 1.41421, which is root-2, which is correct.

Can't assign array element to class variable while overloading "=" operator

I am quite new in C++ programming, so maybe that's why I can't figure out why this assignment is not working.
In my class, I want to overload "=" operator.
I have specified a function, that outputs variables as an array. In overloading, I want to assign those variables to new object.
obj_new = obj_with_variables
overloading:
obj_new_x=obj_with_values_parameters()[0];
obj_new_y=obj_with_values_parameters()[1];
Here is a code:
// Test1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "string"
using namespace std;
class Vector2D
{
public:
Vector2D()
{
}
Vector2D(int& a, int& b)
:x(a), y(b)
{
}
void Drukuj()
{
cout << "wektor [" << x << ',' << y << "] \n";
}
void Wspolrzedne(int&a, int&b)
{
x = a;
y = b;
}
int* Wspolrzedne()
{
int tab[2] = { x,y };
return tab;
}
void operator = (Vector2D& obj)
{
int* a = obj.Wspolrzedne();
cout << a[0] << "\n";
x = a[0];
cout << x << " what? \n";
y = a[1];
}
private:
int x, y;
};
int main()
{
int x1 = 2, x2 = 3;
Vector2D wektor(x1, x2);
wektor.Drukuj();
Vector2D wektor2;
wektor2 = wektor;
wektor2.Drukuj();
wektor.Drukuj();
return 0;
}
The problem is that it assigns some strange values. However, if I don't use a reference, but declare 2 int values (j,k) and assign array element to them [0,1], it works fine.
Also, when using static numbers (for example, instead of a[0] ; use "2") it works fine too.
What is going on?
I would be glad if somebody could point me to right answer/ resources.
Regards,
In your member function int* Wspolrzedne(), you return the address of local variable tab. Accessing this variable once its life time has ended, as you do in your = operator, is undefined behaviour.
Your code has undefined behavior because operator= is accessing invalid data. Wspolrzedne() is returning a pointer to a local variable tab that goes out of scope when Wspolrzedne() exits, thus the a pointer used in operator= is not pointing at valid data.
If you want Wspolrzedne() to return multiple values, you need to have it return (by value) an instance of a struct or class to hold them. Try something more like this:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct Coordinate {
int x;
int y;
};
class Vector2D
{
public:
Vector2D()
: x(0), y(0)
{
}
Vector2D(int a, int b)
: x(a), y(b)
{
}
Vector2D(const Coordinate &c)
: x(c.x), y(c.y)
{
}
Vector2D(const Vector2D &src)
: x(src.x), y(src.y)
{
}
void Drukuj()
{
cout << "wektor [" << x << ',' << y << "] \n";
}
void Wspolrzedne(int a, int b)
{
x = a;
y = b;
}
void Wspolrzedne(const Coordinate &c)
{
x = c.x;
y = c.y;
}
Coordinate Wspolrzedne()
{
Coordinate c = { x, y };
return c;
}
Vector2D& operator=(const Vector2D &obj)
{
Coordinate c = obj.Wspolrzedne();
cout << c.x << ',' << c.y << "\n";
Wspolrzedne(c);
return *this;
}
private:
int x;
int y;
};
On the other hand, there is no real reason to even have operator= call Wspolrzedne() to get the coordinates at all, when it can just access obj.x and obj.y directly instead:
Vector2D& operator=(const Vector2D &obj)
{
x = obj.x;
y = obj.y;
return *this;
}
In which case, you can simply eliminate your operator= altogether, and let the compiler provide a default-generated implementation that does the exact same thing for you.
Your interface is dangerous, as returning raw pointers from functions means the caller must know how to manage it. That is, the caller needs to be astutely aware of the answers to questions like, "should the caller delete the pointer or does the object I got it from retain ownership?" What is this pointer pointing to? If it's an array, now many elements are there? If I must delete it, do I use delete or delete[]?
And so on. This is not good because it's very, very error prone.
Next you have a function that returns a pointer to stack-local data. When the function returns, that memory is already invalid so the return value is always going to result in undefined behavior to read.
int* Wspolrzedne()
{
int tab[2] = { x,y };
return tab; // BAD - returns pointer to function stack data
}
Where does tab live? It's destroyed when the function exits, but you're returning a pointer to it.
This is a dangerous interface and should be changed. Perhaps you should return the values as a pair:
std::pair<int, int> Wspolrzedne()
{
return std::pair{ x,y }; // assuming c++17
// return std::pair<int, int>{x, y}; // older compilers
}
An interface like this avoids pointers, and removes all the issues mentioned above.

Const member function of global variable modifying said variable via global function

The code below
#include <iostream>
class A
{
public:
int x;
double y;
A(int x_, double y_) : x(x_), y(y_)
{
}
void display(void) const;
};
class B
{
public:
static A staticObject;
};
void A::display(void) const
{
std::cout << x << ' ' << y << std::endl;
B::staticObject.x = 42;
B::staticObject.y = 3.5;
std::cout << x << ' ' << y << std::endl;
}
A B::staticObject(19, 29.3);
int main(void)
{
B::staticObject.display();
return 0;
}
prints out
19 29.3
42 3.5
and this makes me wonder:
Is it always safe to let a const member function modify the object it is called from via other means?
Further, is there any worst-case scenario that could be prevented if that member function (here display) were not declared as const?
Your code is valid and works, because display() is const but only with respect to its containing class, A. This has no impact on its ability to modify fields accessed another way--in your case via non-const public access to the two fields.
However, this code is terrible and scary.
what do you think as "safe"?
The only assumption you should make of a const member function is that it will not modify the current object it is in (this pointer). Constness though is not runtime enforced but during compilation time.
So when you "trick" your compiler with the help of static variables it cannot detect that you are actually accessing the same instance. The staticObject in B can also point to another A than the one it's being called from.
To be able to check it would require runtime checks which c++ does not do.

Is it possible to access virtual methods of different ancestors of a polymorphic class through a single pointer?

I am building an interface, where it would be a little bit inconvenient to use separate variables to access individual interfaces, it would be great if somehow I could create a union of the two.
In a file:
struct A{
virtual int auu() { return 41; }
};
struct B{
virtual int boo() { return 43; }
};
In another file:
#include <path to A, B>
struct C : public A, public B{
int auu() { return 20; }
int boo() { return 22; }
};
And another file:
#include <declaration of A and B, but not C>
void doSth(A* a)
{
B * b = dynamic_cast<B*>(a);
/* I can only call auu with a */
a->auu();
/* I can only call boo with b */
b->boo;
/* Something like this would be ideal: */
<??? type> * C_interface = dynamic_interface_cast<B*>(a)
C_interface->auu();
C_interface->boo();
}
So is there to call both auu and boo through only one pointer variable and without the knowledge of C's implementation (not casting it to )? Also I'd like to avoid creating inheritance hierarchy that is NOT in connection with class C.
Probably the answer is no, however I'm curious if an idea like this has come up from the side of the language developers because to my primitive mind it's not a so far fetched idea.
EDIT:
In real, A and B are abstract. A is a Simulation object that has methods like size() and length(). B is an IO interface, implementing getters and setters, but it doesn't know about sizes so I have to use both interfaces in many calculations. C is a specialized Simulation that implements the former 2.
EDIT:
I rewrote the question, maybe it actually makes sense now.
I'll ilustrate the point I made in my comment. It's perfectly legal to cast between siblings, as long as the actual object is derived from both.
#include<iostream>
using namespace std;
struct A{
virtual int auu() { return 41; }
};
struct B{
virtual int boo() { return 43; }
};
struct C : public A, public B{
int auu() { return 20; }
int boo() { return 22; }
};
void take_B(B* bp)
{
cout << bp->boo() << endl; // expected
cout << "(The base class would say "
<< bp->B::boo() << ")" << endl; // base class implementation
A *ap = dynamic_cast<A*>(bp);
if(!ap)
{
cerr << "weird, this cast should be possible!" << endl;
}
else
{
cout << ap->auu() << endl; // should work
cout << "(The base class would say "
<< ap->A::auu() << ")" << endl; // base class implementation
}
}
int main()
{
C c;
take_B(&c);
cout << endl << "... and again:" << endl;
// just to clarify: The actual pointer type is irrelevant.
B *bp = &c;
take_B(bp);
return 0;
}

c++ inheriting. getting data members value of base class

class A
{
public:
A(int a, int b, int c)
:x(a), y(b), z(c)
{}
void display()
{
cout << "x is " << x << endl;
cout << "y is " << y << endl;
cout << "z is " << z << endl;
}
int x;
protected:
int y;
private:
int z;
};
class B : public A
{
public:
B(int x, int y, int z, int extra)
: A(x, y, z), num(extra)
{}
void display()
{
cout << "x is " << x << endl;
cout << "y is " << y << endl;
//cout << "z is " << z << endl;
}
private:
int num;
};
int main()
{
A yo1(1,2,3,);
B yo2(4,5,6,100); //<---
yo2.display(); //I want to print 1 2 3 100
return 0;
}
I have a simply inheritance here. Using inheritance, I want to get A's values and put it into B. How do I access the values of its data members from class A by created a B object? I created an object of class A and gave them the value 1,2,3. In the end, I want to print 1 2 3 100 by using class B's display function.
I understand how I can use the variables from class A but can I also grab their values?
you are confused with concept of inheritance,
B yo2(4,5,6,100);
during this there is separate copy of base class created for the object yo2 which has nothing to do with the object yo1
A yo1(1,2,3,);
the data members x,y,z will have 1,2,3 for yo1 and 4,5,6 for yo2
if you want the output to be
1 2 3 100
then create the object as :
B yo2(1,2,3,100);
you can modify your derived class as
class B : public A
{
public:
B(A& obj, int extra)
: A(obj.x, obj.y, obj.z), num(extra)
{}
void display()
{
A::display();
cout << "num is " << num << endl;
}
private:
int num;
};
and in main you can access as
int main()
{
A obj(1,2,3);
B objB(obj,100);
objB.display();
}
I think you might have misunderstood inheritance.
There is no way for yo2 to know about the values you have given to yo1.
The values yo2 have in A's variables are 4,5,6 respectively.
to illustrate inheritance a little you could rename the display methods "display_a" and "display_b" and then you could access them thus:
yo1.display_a(); // OK. prints values 1,2,3
yo1.display_b(); // Compile error.
yo2.display_a(); // OK. prints values 4,5,6
yo2.display_b(); // OK. prints values 4,5 from variables inherited from A.
To get what happens with the two "display" methods in your original code, look up overloading and the key-word "virtual". Also look up the operator ::
I hope this helps.
First, I think you have misunderstood what inheritance means and yo1 has nothing to do with yo2 at all. Second, you want to use B display function to display A object's members but you are lazy to construct B with argument 1,2,3 because A has constructed using those. Because A's y is protected and A's z is private, you must use a way to copy A object's members to B object if you want achieve your goal. So I think the rajenpandit's answer is right and useful for you.