Cannot access friend class's private members - c++

Would anyone mind helping me with a C++ linking/coding conundrum?
I have a class Shape. Shape needs to use class Center's private data members, x and y coordinates. I declare friend class Shape; and then #include "center.h" in Shape.h. In Shape.cpp, I define my ostream& operator<< (ostream& ostr, const Center& c) function, which uses c.xCord; c.yCord to access Center's private data members.
When I attempt to compile Shape.cpp I get access errors for those data variables like I haven't declared Shape as a friend class. I have a feeling this has something to do with the linking order at compile time. How can I fix this?
#ifndef CENTER_H
#define CENTER_H
class Center
{
public:
Center(double x, double y) { xCord = x; yCord = y; }
// constructor
friend class Shape;
// allow Shape to use Center's x and y values
private:
double xCord;
// X-coordinate
double yCord;
// Y-coordinate
};
#endif
#ifndef SHAPE_H
#define SHAPE_H
#include "center.h"
#include <iostream>
using namespace std;
class Shape
{
public:
Shape(double x, double y) : s_center(x, y) {}
// constructor
void moveCenter();
// moves the center of the shape
friend ostream& operator<< (ostream& ostr, const Center& c);
// allows the printing of the Center object
virtual void printCenter();
// returns the center of the shape
virtual double printArea();
// returns the area of the shape
virtual bool checkSurface(Shape& s) = 0;
// checks if the shape can fit into
// a given surface
virtual double findArea() = 0;
// calculates the area of the shape
private:
Center s_center;
// center of the shape
};
#endif
// in shape.cpp
ostream& operator<< (ostream& ostr, const Center& c)
{
ostr << "(" << c.xCord << ", " << c.yCord << ")";
return ostr;
}

Per Paragraph 11.3/10 of the C++11 Standard:
Friendship is neither inherited nor transitive. [...]
If class A is a friend of class B, and function f() is a friend of class A, this does not make f() a friend of class B as well.
You should declare your operator << as friend of class Center if you want it to access private member variables of Center:
#ifndef CENTER_H
#define CENTER_H
#include <ostream>
class Center
{
public:
Center(double x, double y) { xCord = x; yCord = y; }
friend class Shape;
friend std::ostream& operator<< (std::ostream& ostr, const Center& c);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
private:
double xCord;
double yCord;
};
#endif

Your operator << has nothing to do with class Shape. The friendship does not extend to the operator. You need to declare that specific operator as a friend.

Related

How do I create a duplicate of an object in C++ when working with classes and objects (Object Oriented Programming)

Create a friend function to duplicate a Shape object. The input parameter of this function will be
a Shape object, and it will return the duplicated object. Use the compare function to show that
the duplication is successful.
In this question, we were supposed to create a "Shape" class and add two private members: length and width (of the type double). Then, compute the area and parameter using those values. Also, we had to create two instances in the main and take user inputs for the values of length and width. All of this must be done using friend functions.
Could anyone please help with the duplication thing?
Okay, so I have compared both objects using the operator==() function. Does it mean that creating a duplicate object is similar to creating a copy constructor?
This is the code that I've written so far:
#include <iostream>
using namespace std;
// all functions need to be friend functions
class Shape {
private:
double length, width;
public:
Shape();
Shape(double length, double width);
friend double area(const Shape &sh3);
friend double perimeter(const Shape &sh3);
friend bool operator==(const Shape &sh1, const Shape &sh2);
friend void Shape(const Shape &sh3, const Shape &sh1, const Shape &sh2);
};
Shape::Shape() {
width = 0.0; length = 0.0;
}
Shape::Shape(double length, double width) {
this->length = length; this->width = width;
}
double area(const Shape &sh3) { // friend fucntion to compute the area!
return (sh3.width*sh3.length);
}
double perimeter(const Shape &sh3) { // friend fucntion to compute the perimeter!
return (2*(sh3.length) + 2*(sh3.width));
}
bool operator==(const Shape &sh1, const Shape &sh2) { // friend function to compare the area of two objects!
if (sh1.length == sh2.length && sh1.width == sh2.width) {
cout << "Both shapes are equal\n";
return true;
}
}
//friend function to create a duplicate of the object:
void Shape(const Shape &sh3, const Shape &sh1, const Shape &sh2) { // calling the copy constructor
class Shape sh4;
if (operator==(sh1, sh2) == true) {
sh4.length = sh3.length;
sh4.width = sh4.width;
}
}
int main () {
double l, w; cout << "Enter the values for shape 1: "; cin >> l >> w;
class Shape sh1(l, w); // onject 2
double l1, w1; cout << "Enter the values for shape 2: "; cin >> l1 >> w1;
class Shape sh2(l1, w1); // object 1
class Shape sh3; // object3 using the preset values for l and w
operator == (sh1, sh2); // to compare both objects
return 0;
}
You're almost there... I'd just like to point out a couple of error in your code.
You can't call your function Shape(), there is a class called Shape, and you cannot declare a friend constructor.
class Shape {
private:
double length, width;
public:
Shape();
Shape(double length, double width);
friend double area(const Shape &sh3);
friend double perimeter(const Shape &sh3);
friend bool operator==(const Shape &sh1, const Shape &sh2);
// friend void Shape(const Shape &sh3, const Shape &sh1, const Shape &sh2);
// since we're going to copy Shapes We might as well define a copy contructor.
Shape(const Shape& other)
{
length = other.length;
/* etc...*/
}
// One friend function that takes in a const ref and returns an object.
friend Shape Duplicate(const Shape& other)
{
return other; // calls the copy constructor
// if no copy constructor, use another construtor to initialize object
return Shape(other.length, other.width);
}
};
// ...
Shape a(1., 2.);
Shape b = Duplicate(a); // spawning a new Shape
if (a == b) // calling operator ==
// do something

Why doen't my code work? c++ operator [duplicate]

This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 6 years ago.
//main()
#include <iostream>
#include "Circle.h"
#define PI 3.1415965 //defining the pi number
using namespace std; //I want to create a class that has the characteristics of a circle
int main()
{
Circle c1(1); //making a class object
cout<<c1; //using the operator<< after overloading it
return 0;
}
//circle.h
#include <iostream> //I'm just practicing with these things so my code will probably have some mistakes but I really cannot understand where is the right place for the operator<< because I receive errors all the time
using namespace std;
class Circle //creating the class circle
{
public:
Circle(); //constructor with zero members
Circle(float r); //constructor with one member
float getPerimetre(); //getting the perimeter of the circle
float getArea(); //getting the area of the circle
friend ostream &operator<<(ostream &mystream, Circle &p); //making the operator<<
private:
float radius; //private members
};
#endif // CIRCLE_H
//circle.cpp
#include "Circle.h"
#include <iostream>
#define PI 3.14159265 //defining the pi number
using namespace std;
Circle::Circle() //creating the constructor with zero members
{
radius=0;
Circle::Circle(float r) //creating the constructor with one member
{
radius=r;
}
float Circle::getPerimetre() //explaining the functions get perimetre
{
return (2*PI*radius);
}
float Circle::getArea() //and get area
{
return (PI*radius*radius);
}
ostream &operator<<(ostream &mystream, Circle &p) //i'm not sure if this is the right place to write this
{
mystream<<radius<<", "<<getPerimetre()<<", "<<getArea()<<endl;
return mystream;
}
out from all the things that I've read I really cannot understand where is the correct spot to write this operator and why I keep receiving errors when I run the project. I am new to this and also to this site so any help would be very apreciated
Your operator<< is at good place, however since it isn't member function you can't access members without object:
p.radius instead of radius
p.getPerimetre() instead of getPerimetre()
p.getArea() instead of getArea()
ostream &operator<<(ostream &mystream, Circle &p) //i'm not sure if this is the right place to write this
{
mystream<<radius<<", "<<p.getPerimetre()<<", "<<p.getArea()<<endl;
return mystream;
}
friend ostream &operator<<(ostream &mystream, Circle &p);
should be
friend ostream &operator<<(ostream &mystream, const Circle &p);
and the implementation should look like
ostream &operator<<(ostream &mystream, const Circle &p)
{
mystream<<p.radius<<", "<<p.getPerimetre()<<", "<<p.getArea()<<endl;
return mystream;
}
this also requires that you classify getPerimetre() and getArea() as const functions in your class declaration
class Circle {
public:
// ...
float getPerimetre() const;
// ^^^^^
float getArea() const;
// ^^^^^
// ...
};
and definition
float Circle::getPerimetre() const {
// ^^^^^
return (2*PI*radius);
}
float Circle::getArea() const {
// ^^^^^
return (PI*radius*radius);
}

Friend function C++

Why doesn't this work?
I use friendly function in my code but there is an error so I can not find it. please help.
#include<iostream>
#include<cstdlib>
using namespace std;
class Circle{
private:
int x;
public:
Circle(int x1=5){
x=x1;
friend std:ostream & operator<<(const Circle & c, std::ostream & os)
{
return os<<c.x
}
}
};
int main()
{
Circle s;
cout<< s;
system("pause");
return 0;
}
Four problems:
You've defined the friend function inside the constructor. Move it outside so that it's its own function.
Replace std:ostream with std::ostream
Swap the order of the parameters.
Add a semicolon after return os<<c.x
Final result:
class Circle{
private:
int x;
public:
Circle(int x1=5){
x=x1;
}
friend std::ostream & operator<<(std::ostream & os, const Circle & c)
{
return os<<c.x;
}
};
friend std:ostream & operator<<(const Circle & c, std::ostream & os)
{
return os<<c.x
}
you should declare this function outside the constructor.
The friend function needs to be declared at the same level as the constructor, not inside it.

Friend function can't access class variables

I thought that friend functions could access class variables as in how I try to do v.x, v.y, v.z in the << function. But it doesn't compile. It says it's unable to resolve identifier at those lines.
Also I'm trying to learn how to use namespaces. Even though I use the namespace vec in the implementation file I still have to include Vector:: before everything so what's the point?
Header file:
#ifndef VECTOR_H
#define VECTOR_H
namespace vec {
class Vector {
private:
double x, y, z;
public:
Vector(double, double, double);
friend std::ostream& operator<<(std::ostream&, const Vector&);
};
}
#endif /* VECTOR_H */
.cpp file:
#include "Vector.h"
#include <iostream>
using namespace vec;
//Constructor
Vector::Vector(double x1 = 0, double y1 = 0, double z1 = 0) {
x = x1;
y = y1;
z = z1;
}
//Operators
std::ostream& operator<<(std::ostream& out, const Vector& v) {
out<<"<"<<v.x<<", "<<v.y<<", "<<v.z<<">";
return out;
}
Friend functions aren't member functions, and operator<< needs to not be a member in order to have a left side of ostream. Change it to a free function:
std::ostream& operator<<(std::ostream& out, Vector v) {
^^ no qualification
I would also take the vector by const reference instead of by value.
Your friend function belongs to the namespace vec and must be defined as such.
Change it to:
std::ostream &vec::operator << (std::ostream &out , const Vector &v) { //etc

Problems with forward declaration - Friend functions and line / point classes

I have a demo program for understanding of friend function. I am stuck up with errors related to forward declaration stuff, I guess.
I have a point class which has x & y co-ordinates. The line class has two objects of point class. Now I have a function in line class which will calculate the slope of the line.
This is my program:
#include <iostream>
using namespace std;
class point
{
int x,y;
public:
point(int,int);
point();
friend float line::slope();
};
point::point(int a, int b)
{
x=a;
y=b;
}
point::point()
{
}
class line
{
point p1,p2;
public:
line(point,point);
float slope();
};
line::line(point p1, point p2)
{
this->p1=p1;
this->p2=p2;
}
float line::slope()
{
float s;
s=((float)p2.y-p1.y)/(p2.x-p1.x);
return s;
}
int main()
{
float sl;
point obj(5,10);
point obj1(4,8);
line obj3(obj,obj1);
sl=obj3.slope();
cout<<"\n slope:"<<sl;
return 0;
}
It is giving me compiler errors with respect to forward declarations due to the following:
When I try to define my line class first, it does not know about the point class. Even if I forward declare the point class, that wont suffice coz to create objects of the point class, the compiler should know the size of the point class and hence the whole class itself. Understood it through explanation in this answer: https://stackoverflow.com/a/5543788
If I define the point class first, it needs to know the friend function slope and hence the class line.
So I tried to provide the forward declaration for the line class and the slope function like this before defining the point class:
class line;
float line::slope();
class point
{
int x,y;
public:
point(int,int);
point();
friend float line::slope();
};
Now this gives me the following errors:
friend1.cpp:5: error: invalid use of incomplete type ‘struct line’
friend1.cpp:4: error: forward declaration of ‘struct line’
friend1.cpp:13: error: invalid use of incomplete type ‘struct line’
friend1.cpp:4: error: forward declaration of ‘struct line’
friend1.cpp: In member function ‘float line::slope()’:
friend1.cpp:9: error: ‘int point::y’ is private
friend1.cpp:43: error: within this context
friend1.cpp:9: error: ‘int point::y’ is private
friend1.cpp:43: error: within this context
friend1.cpp:9: error: ‘int point::x’ is private
friend1.cpp:43: error: within this context
friend1.cpp:9: error: ‘int point::x’ is private
friend1.cpp:43: error: within this context
.3. Next I tried to separate out the point class in point.h and point.cpp and line class in line.h and line.cpp. But still here there is a dependency on each other.
Though this should be possible theoretically, I cannot figure it out how to get it working.
Looking out for answers.
Thanks,
Raj
PS: This program is an effort to demonstrate the usage of friend functions alone. Where friend functions are of two types, this is an effort to deal with the second of this kind:
Friend functions which are independent.
Friend functions which are members of another class.
So, usage of friend classes are ruled out in this case.
Add line as a friend, not just a method:
friend class line;
Other remarks:
separate declarations from the implementations in header and implementation files.
prefer full qualification over using directives (i.e. remove using namespace std; and use std::cout instead.
prefer pass-by-reference for complex types - change line(point,point); to line(const point&, const point&);
EDIT For educational purposes - You can't declare that specific function as friend as the code is now because there's no full definition of the line class. Ergo, the following is the only approach:
class point;
class line
{
point *p1,*p2;
public:
line(point,point);
float slope();
};
class point
{
int x,y;
public:
point(int,int);
point();
friend float line::slope();
};
You forward-declare point and change the point members in line to point* (because point isn't a complete type yet). In point you now have the full definition of the line class, so you can declare the method as friend.
EDIT 2: For this particular scenario, it's not possible using point objects inside line because you'd need the full type. But line would also have to be fully defined in order to declare its member as friend.
Just make Line a friend of Point
class point
{
friend class line;
...
};
There's very little purpose in declaring individual methods as friends.
You can create a helper functor to calculate slope. This allows you to make the method of the functor a friend of the point without involving line.
class point;
class line;
struct slope {
float operator () (const point &, const point &) const;
float operator () (const line &) const;
};
class point {
int x,y;
public:
point(int a,int b) : x(a), y(b) {}
point() {}
friend float slope::operator ()(const point &, const point &) const;
};
class line {
point p1,p2;
public:
line(point a,point b) : p1(a), p2(b) {}
float slope() { return ::slope()(*this); }
friend float slope::operator ()(const line &) const;
};
With the implementations:
float slope::operator () (const point &p1, const point &p2) const {
float s;
s=((float)p2.y-p1.y)/(p2.x-p1.x);
return s;
}
float slope::operator () (const line &l) const {
return (*this)(l.p1, l.p2);
}
Under normal circumstances, I would avoid using friend here at all.
Prefer to add a function to point:
float slope_to(const point& other)
{// Not checked, just translated from your implementation
return ((float)other.y-y)/(other.x-x);
}
And implement:
float line::slope()
{
return p1.slope_to(p2);
}
This way line doesn't care about point's implementation and will not need to be changed when you implement 3D points.
Here is a demonstration of a friend of a free function (1.):
#include <iostream>
class point
{
int x, y;
public:
point(int, int);
friend std::ostream& operator <<(std::ostream& os, const point& p);
};
std::ostream& operator <<(std::ostream& os, const point& p)
{
return os << '(' << p.x << ", " << p.y << ')';
}
point::point(int a, int b)
:x(a)
,y(b)
{
}
int main()
{
point obj(5, 10);
std::cout << "\n point " << obj;
}
Here is an example building on your own code to have a friend of a member function (2.).
#include <iostream>
#include <memory>
using namespace std;
class point;
class line
{
std::auto_ptr<point> p1, p2;
public:
line(point&, point&);
float slope();
};
class point
{
int x, y;
public:
point(int, int);
friend float line::slope();
};
point::point(int a, int b)
:x(a)
,y(b)
{
}
line::line(point& p1, point& p2)
:p1(new point(p1))
,p2(new point(p2))
{
}
float line::slope()
{
return ((float)p2->y - p1->y) / (p2->x - p1->x);
}
int main()
{
point obj(5, 10);
point obj1(4, 8);
line obj3(obj, obj1);
cout << "\n slope:" << obj3.slope();
}
In order to reference point from within line, I use (auto_) pointers and references, since the class is declared at that point but not defined. line::slope() is declared in time for me to reference it as a friend of point. This circular dependency is a terrible code smell and should be avoided.
you refer to the line class in friend float line::slope(); before the class is defined.
just add the line class line; before the definition of the Point class
also change friend float line::slope(); to friend class line;