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

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;

Related

Overloading operator< containing class object

Having trouble with overloading operator<. I am trying to overload the operator< so that I can sort my Line2D object based on pt1's x. But I am having trouble figuring out how to declare the function.
I am getting the error:
object has type qualifiers that are not compatible with the member function "Point2D::getX".
What I have tried: removing const, putting Point2D &l2dobj instead.
class Line2D
{
private:
Point2D pt1;
Point2D pt2;
public:
bool operator<( const Line2D &l2dobj)
{
return (pt1.getX() < l2dobj.pt1.getX());
}
}
class Point2D
{
protected:
int x;
int y;
public:
int getX();
int getY();
}
Point2D::getX doesn't accept const instance, you cannot apply it on l2dobj while it is a const reference, change getX (and a priori getY) to :
class Point2D
{
protected:
int x;
int y;
public:
int getX() const;
int getY() const;
};
As a general way declare the methods const the more you can, and same for their parameters

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);
}

Cannot access friend class's private members

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.

C++ operator overriding w/ arguments from 2 classes

I'm new to object oriented programming and I'm wondering if it's possibile to create an operator for one class which will use arguments from this class and another one, declared by me.
The problem I have to solve is a linear translation on a given point. So I created classes Point and LinearTranslation and basically what I want to do is to create an operator
Point operator* (Point p, LinearTranslation l)
which would take Point p, do the translation l and then return Point. I'm getting weird errors though: Point operator*(int)’ must have an argument of class or enumerated type or that LinearTranslation has not been declared.
Is it even possibile?
ok i'm posting only a bit because it's kind of assignment so I have class Point.h
sorry for the mess but I'm trying a bit everything and it's not working for me.
#include "LinearTranslation.h"
class Point {
public:
int N;
double* coordinates;
public:
Point(int, double*);
virtual ~Point();
double operator[](int a);
//friend Point operator*(LinearTranslation l);
friend Point translation(LinearTranslation l);
};
LinearTranslation.h
#include "Point.h"
class LinearTranslation {
private:
int N;
double* vector;
double** matrix;
public:
//friend class Point;
LTrans(int,double*,double**);
LTrans(int);
virtual ~LTrans();
void write_vector();
void write_matrix();
LinearTranslation operator+(const LinearTranslation&);
friend Point& translation(LTrans l, Point p);
//friend Point& operator* (Point p, LTrans l);
};
in your class declaration:
//friend Point operator*(LinearTranslation l);
a friend operator overloading function takes two parameters for the function, you only declare one in your code. The most common example of a friend function is using the overloaded operator << like so:
friend ostream& operator<<(ostream& output, const Point& p);
note that this function takes the output as its first parameter, and the point as its second parameter.
Your fix would be to add in your operand to the function
friend Point operator*(LinearTranslation l, const int& MULT);

Returning a struct from a class method

I have a header file that looks something like the following:
class Model {
private:
struct coord {
int x;
int y;
} xy;
public:
....
coord get() const {
return xy;
}
};
And in yet another file (assume ModelObject exists):
struct c {
int x;
int y;
void operator = (c &rhs) {
x = rhs.x;
y = rhs.y;
};
} xy;
xy = ModelObject->get();
The compiler throws an error that says there is no known covnersion from coord to c.
I believe it is because it doesn't know about coord type because it is declared inside of a class header. I can get around that by declaring the struct outside of the class, but I was wondering if it is possible to do the way I am, or is this generally considered bad practice
You would need an implicit conversion operator for Model::coord to c. For information on how to do this, I recommend taking a look at C++ Implicit Conversion Operators.
Also, when you mentioned "It does not know the type because it is in a class", you would use Model::coord as the struct type to the outside world (as long as coord is public, which in your current case it is not).
The code you have provided has two major problems:
1. You have not given a conversion from struct coord to struct c.
2. You can not use struct coord outside class Model because it is declared private.
Even if struct coord and struct c are similar, the compiler has very limited psychic powers. For the compiler the two structs are different even if they do essentially the same. One way to solve this is to give struct c an adequate assignement operator which takes a type of struct coord:
strutc c {
...
void operator = (const coord& rhs) { ... }
};
You have to make struct coord more public to be used outside class Model.
You can do this by:
a) declaring struct coord outside the class Model or
b) declaring it public inside class Model
If you do the latter you have to use the qualified name Model::coord to access the struct.
Remarks:
Consider changing the method
coord Model::get() const;
to
const coord& Model::get() const;
A subtle change that makes big difference. This saves an implicit construction of struct coord on the stack.
Consider changing the the operator
void c::operator = (c &rhs);
to
void c::operator = (const c& rhs);
because the assignment operator does not change the given argument struct c.
Const correctness is not just syntactic sugar but mandatory and it improves readability.
So this is my suggestion:
class Model {
public:
struct coord {
int x; int y;
};
private:
coord xy;
public:
const coord& get() const { return xy; }
};
struct c {
int x; int y;
void operator = (const c &rhs) { x = rhs.x; y = rhs.y; };
void operator = (const Model::coord &rhs) { x = rhs.x; y = rhs.y; };
};
Adding a constructor of c taking a coord is enough to make the compiler do the conversion. Now why do you have 2 different types for this ? Can't it be better to factorize this coord class out of Model and use them at both point ?