Output duplicates from ostream operator

How do I get rid of the duplicates in the output below? Center and axis have duplicate points in them. I've been thinking for so long now, and still can't figure it out. Need any help there is possible. Refer to the ostream << operator in class Square. The problem I'm facing lies over there. Do not know what to do. Any help is appreciated. thanks! NOTE: Do not modify the main(). I know the inheritance is weird. But it is what my school wants. Program is compilable.

Output:
BEGIN
Square with center (0.015971,0.0496622)(0.834645,0.550788), edge length 2.22648, and axis vector (0.015971,0.0496622)(0.834645,0.550788)
Square with center (0.407785,0.360472)(0.975136,0.221607), edge length 1.68167, and axis vector (0.407785,0.360472)(0.975136,0.221607)
Square with center (0.982257,0.108734)(0.0517639,0.998659), edge length 0.416612, and axis vector (0.982257,0.108734)(0.0517639,0.998659)
END

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#include <iostream>
#include <algorithm>
#include <functional>
#include <list>
#include <cmath>
 
class Object
{
public:

private:
	float d;

public:
	Object(float n) : d(n){}
	Object(){}
	float depth() const
	{
		return d;
	}
	
	struct PointType
	{
		float x2;
		float y2;
		PointType( float x1,  float y1) :x2(x1),y2(y1){}
		PointType(){}
		float x()
		{
			return x2;
		}
		float y()
		{
			return y2;
		}
		PointType center()
		{
		return *this;
		}
		friend std::ostream& operator<<(std::ostream& os, const 
		PointType& p)
		{   
			os << "(" << p.x2 << "," << p.y2<<")";
			return os;              
		}
	};
	struct VectorType
	{
		float tx;
		float ty;
		VectorType( float tx1,  float ty1) :tx(tx1),ty(ty1){}
		VectorType(  ){}
	};
	virtual void render() const
	{
	}
	virtual ~Object()
	{
	}
};
class Point :public Object 
{
 
private:
    PointType mpoint;
	
public:

    Point(const PointType& pt, float& y1) :Object(y1), mpoint(pt) {}
	Point(const PointType& pt):mpoint(pt){}
	Point(){}
	
  	 Point center() const
	{
	     return *this;
	}
	 float x()
	{
		return mpoint.x2;

	}
	 float y()
	{
		return mpoint.y2;
	}
 
	friend std::ostream& operator<<(std::ostream& os, const Point& p)
	{
		os << p.mpoint; 
		return os;
	}
 
};
class Circle : public Point 
{ 
	private:
	Object::PointType m_pt;
 	float r;
	public:  
	
	Circle(const PointType pts, float rad, float dep) 
	: Point(m_pt,dep),m_pt(pts),r(rad) {}
	
	Circle(const PointType pts, float rad):m_pt(pts),r(rad){}
	
	Circle(){}
	
	float radius() const
	{
		return r;
	}
	
	Circle center() const
	{
		return *this;	
		
	};
	 float x()
	{
		return m_pt.x2;

	}
	  float y()
	{
		return m_pt.y2;
	}
 
	virtual void render() const{}
	friend std::ostream& operator<<(std::ostream& os, const Circle& c)
	{
		os << c.m_pt; 
		return os;
	}
};
class Square: public Circle  
{
	private:
	Object::PointType s_pt;
	Object::VectorType v_pt;
	float a=getRadius();
	
	public:
	Square(const PointType spts,const VectorType vpts,float depth) :
	Circle(spts,a,depth),s_pt(spts),v_pt(vpts){}
	
	Square(const Object::PointType& spts, const VectorType vpts):s_pt(spts),v_pt(vpts){}
	
	Square axis() const
	{
		return *this;
	}
	Square center() const
	{
		 return *this;
	}
 
	float radius() const
	{
		  return a;
	}
	float getRadius() const
	{
		float rad= sqrt(v_pt.tx * v_pt.tx + v_pt.ty * v_pt.ty); 
 
		return rad;
	}
	float x() const
	{
		return v_pt.tx/radius();
	}
	float y() const

	{
		return v_pt.ty/radius();
	}
	virtual void render() const
	{
	}
	friend std::ostream& operator<<(std::ostream& os, const Square& s)//this
	{
		os <<s.s_pt <<"("<<s.x()<< ","<<s.y()<<")"; 
		return os;
	}
};
class VisibleSquare : public Square
{
public:
	VisibleSquare(const Object::PointType& point,
		const Object::VectorType& vector) : Square(point, vector)
	{
	}
	void render() const override
	{
		std::cout << "Square with center " << center()
			<< ", edge length " << (2 * radius())
			<< ", and axis vector " << axis()
			<< std::endl;
	}
};

// A simple pseudo-random number generator.
class PseudoRandom
{
	const int A = 101;
	const int B = 919;
	const int C = 10619863;

	int _current;

public:
	PseudoRandom() :
		_current(0)
	{
	}

	int operator()()
	{
		_current = (A * _current + B) % C;
		_current += (_current < 0) ? C : 0;
		return _current;
	}

	int operator()(int n)
	{
		return (*this)() % n;
	}

	float operator()(float a, float b)
	{
		int result = (*this)();
		return a + (b - a) * static_cast<float>(result) / float(C);
	}
};

int main()
{
	std::list<Object*> objects;
	PseudoRandom random;

	for (int i = 0; i < 10; ++i)
	{
		switch (random(5))
		{
			case 0:
			{}
			case 1:
			{}
			case 2:
			{
				const Object::PointType point(random(0, 1), random(0, 1));
				const Object::VectorType vector(random(0, 1), random(0, 1));
				objects.push_back(new VisibleSquare(point, vector));
				break;
			}
			case 3:
			{}
			case 4:
			{}
		}
	}

	std::cout << "BEGIN" << std::endl;

	std::for_each(objects.begin(), objects.end(), std::mem_fn(&Object::render));
	
	std::cout << "END" << std::endl;
	
	for (const Object* object : objects)
	{
		delete object;
	}
	objects.clear();
}
Last edited on
Well, the duplication comes in line 181:
os <<s.s_pt <<"("<<s.x()<< ","<<s.y()<<")";
which should either be
os << "("<<s.x()<< ","<<s.y()<<")";
or
os <<s.s_pt;

That removes the duplication ... but probably not the illogical code. Since when has a Square been a type of Circle?
Last edited on
@lastchance, I was just looking at this too. But s.x() and s.y() both use s.v_pt, not s.s_pt.

I have no idea what's up with this code. It's funny that a Square inherits from a Circle. Squaring the circle? Maybe the problem is in the wacky hierarchy:
Object
  Point
    Circle
      Square
        VisibleSquare

Then there's the weird center() functions that just return *this; .
In particular, Square has this

1
2
    Square axis     () const { return *this; }
    Square center   () const { return *this; } 

axis and center return the same thing, which I guess explains the duplicates.
Last edited on
Hi dutch, what do you think should be returned then? I just can't figure it out.
I can't figure it out either. Your code is senseless to me. Why is a square a circle? What in the world are you trying to do?
Last edited on
Hi dutch, its actually due to the interfaces that it has. For eg. Circle has Iscalable interface and square has Irotatable interface and square needs to inherit from circle because of its the Iscalable interface so it can used the scale function. I did not include them in my code as it is not required now. Does this make a little more sense?
Last edited on
Rough example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#include <array>
#include <cmath>
#include <chrono>
#include <functional>
#include <iostream>
#include <random>
#include <vector>


// ***************************************************************************
//                          class PointType
// ***************************************************************************
struct PointType {
    double m_x {};
    double m_y {};

    PointType() = default;
    PointType(double x_arg, double y_arg);
    double x() const;
    double y() const;

//friend:
    friend std::ostream& operator<< (std::ostream& os, const PointType& p);
};


PointType::PointType(double x_arg, double y_arg)
    : m_x { x_arg }
    , m_y { y_arg }
{
}


double PointType::x() const
{
    return m_x;
}


double PointType::y() const
{
    return m_y;
}


// PointType friend
std::ostream& operator<< (std::ostream& os, const PointType& p)
{
    os << "(" << p.m_x << " , " << p.m_y << ")";
    return os;
}


// ***************************************************************************
//                          class SegmentType
// ***************************************************************************
struct SegmentType {
    PointType p_one {};
    PointType p_two {};

    SegmentType() = default;
    SegmentType(PointType p_one_arg,  PointType p_two_arg);
};


SegmentType::SegmentType(PointType p_one_arg, PointType p_two_arg)
    : p_one { p_one_arg }
    , p_two { p_two_arg }
{
}


// ***************************************************************************
//                             class Object
// ***************************************************************************
// ABC
class Object {
public:
    Object(double depth_arg = 0);
    Object(const PointType& center_arg, double depth_arg = 0);
    virtual ~Object() = default;    // well, ok, but this class doesn't
                                    // manage anything on the heap...

    PointType center() const;
    double depth() const;
    virtual void render() const;
    virtual Object& scale(double) = 0;

protected:
    PointType m_center;
    double m_depth {};
};


Object::Object(double depth_arg)
    : m_depth { depth_arg }
{
}


Object::Object(const PointType& center_arg, double depth_arg)
    : m_center { center_arg }
    , m_depth { depth_arg }
{
}


PointType Object::center() const
{
    return m_center;
}


double Object::depth() const
{
    return m_depth;
}


// If you don't want to define it here, you can make it pure too:
void Object::render() const
{
}


// ***************************************************************************
//                             class Point
// ***************************************************************************
class Point : public Object {
public:
    Point() = default;
    Point(const PointType& pt, double depth_arg = 0);

    virtual void render() const override;
    virtual Point& scale(double) override;

//friend:
    friend std::ostream& operator<< (std::ostream& os, const Point& p);
};


Point::Point(const PointType& pt, double depth_arg)
    : Object { pt, depth_arg }
{
}


void Point::render() const
{
    // Waiting for a better implementation...
    std::cout << '\n' << *this << '\n';
}


Point& Point::scale(double)
{
    return *this;       // a Point should not scale, IMHO
}


// friend Point
std::ostream& operator<< (std::ostream& os, const Point& p)
{
    os << "Point " << p.m_center;
    return os;
}


// ***************************************************************************
//                             class Circle
// ***************************************************************************
class Circle : public Object {
public:
    Circle() = default;
    Circle(const PointType& center_arg,
           double radius_arg,
           double depth_arg = 0);

    Circle(const PointType& center_arg,
           const PointType point_on_circumference,
           double depth_arg = 0);


    double radius() const;
    virtual void render() const override final;
    virtual Circle& scale(double radius_arg) override final;

//friend:
    friend std::ostream& operator<< (std::ostream& os, const Circle& c);

private:
    double m_radius;
};


Circle::Circle( const PointType& pts,
                double radius_arg,
                double depth_arg )
    : Object { pts, depth_arg }
    , m_radius { radius_arg }
{
}


Circle::Circle(const PointType& center_arg,
               const PointType point_on_circumference,
               double depth_arg)
    : Object { center_arg, depth_arg }
{
    // Pythagorean theorem:
    double cathetus_1 {
        std::fabs( point_on_circumference.m_x - m_center.m_x )
    };
    double cathetus_2 {
        std::fabs( point_on_circumference.m_y - m_center.m_y )
    };
    m_radius = std::sqrt(   std::pow( cathetus_1, 2 )
                          + std::pow( cathetus_2, 2 ) );
}


double Circle::radius() const
{
    return m_radius;
}


void Circle::render() const
{
    // ???
    std::cout << '\n' << *this << '\n';
}


Circle& Circle::scale(double radius_arg)
{
    // ...
    m_radius = radius_arg;
    // ...
    return *this;
}


// Friend Circle:
std::ostream& operator<< (std::ostream& os, const Circle& c)
{
    os << "Circle: centre is " << c.m_center << " and radius is "
       << c.m_radius;
    return os;
}


// ***************************************************************************
//                         class Rectangle
// ***************************************************************************
class Rectangle: public Object {
public:
    Rectangle(const PointType& center_arg,
              double shortest_arg,
              double longest_arg,
              double m_depth = 0);


    std::array<PointType, 4> findVertices() const;
    double diagonal() const;
    double longestSide() const;
    double shortestSide() const;

    virtual void render() const override;
    virtual Rectangle& scale(double howmuch) override;

//friend:
    friend std::ostream& operator<< (std::ostream& os, const Rectangle& r);

private:
    double shortest;
    double longest;
};


Rectangle::Rectangle(const PointType& center_arg,
                     double shortest_arg,
                     double longest_arg,
                     double depth)
    : Object { center_arg, depth }
    , shortest { shortest_arg }
    , longest { longest_arg }
{
}


std::array<PointType, 4> Rectangle::findVertices() const
{
    // assuming the rectangles stretches horizontally:
    return {
        PointType { m_center.m_x - longest / 2,
                    m_center.m_y - shortest / 2 },    // top left

        PointType { m_center.m_x + longest / 2,
                    m_center.m_y - shortest / 2 },    // top right

        PointType { m_center.m_x + longest / 2,
                    m_center.m_y + shortest / 2 },    // bottom right

        PointType { m_center.m_x - longest / 2,
                    m_center.m_y + shortest / 2 }    // bottom left
    };
}


double Rectangle::diagonal() const
{
    // Pythagorean theorem:
    return std::sqrt( std::pow( shortest, 2 ) + std::pow( longest, 2) );
}


double Rectangle::longestSide() const
{
    return longest;
}


void Rectangle::render() const
{
    std::cout << '\n' << *this << '\n';
    // ...
}


Rectangle& Rectangle::scale(double howmuch)
{
    //...
    longest -= howmuch;
    shortest -= howmuch;
    //...
    return *this;
}


// Friend Rectangle
std::ostream& operator<< (std::ostream& os, const Rectangle& r)
{
    auto arr { r.findVertices() };
    os << "Rectangle:\n"
          "upper-left: "     << arr.at(0)
       << "; upper-right: "  << arr.at(1)
       << "\nbottom-right: " << arr.at(2)
       << "; bottom-left: "  << arr.at(3)
       << "\nbase: " << r.longest << "; height: " << r.shortest
       << "; diagonal: " << r.diagonal();
    return os;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// ***************************************************************************
//                            class Square
// ***************************************************************************
class Square : public Rectangle {
public:
    Square(const PointType& center_arg,
           double side);

    void render() const override final;
    virtual Square& scale(double howmuch) override final;
};


Square::Square(const PointType& center_arg, double side)
    : Rectangle(center_arg, side, side)
{
}


void Square::render() const
{
    Rectangle::render();
}


Square& Square::scale(double howmuch)
{
    Rectangle::scale(howmuch);
    return *this;
}


// ***************************************************************************
//                          class PseudoRandom
// ***************************************************************************
// A simple pseudo-random 'double' number generator.
class PseudoRandom {
public:
    PseudoRandom(double max_val_arg = 0.0);

    int operator()()
    {
        std::uniform_real_distribution dst(0.0, max_val);
        return static_cast<int>( dst( eng ) );
    }

    int operator()(int max_value)
    {
        max_val = static_cast<double>(max_value);
        return operator ()();
    }

    double operator()(double min, double max)
    {
        max_val = max;
        std::uniform_real_distribution dst(min, max_val);
        return dst( eng );
    }

private:
    static std::mt19937 eng;
    double max_val {};
};


std::mt19937 PseudoRandom::eng {
    static_cast<unsigned>(
        std::chrono::high_resolution_clock::now().time_since_epoch().count()
    )
};


PseudoRandom::PseudoRandom(double max_val_arg)
    : max_val { max_val_arg }
{
}


// ***************************************************************************


int main()
{
    std::vector<Object*> objects;
    PseudoRandom pr;

    for (int i = 0; i < 10; ++i) {
        std::cout << "Creating random ";
        switch ( pr(4) ) {
        case 0:
            std::cout << "Point.\n";
            objects.push_back(
                reinterpret_cast<Object*>(
                    new Point( { pr(1.0, 20.0), pr(1.0, 20.0) } )
                )
            );
            break;

        case 1:
            std::cout << "Circle.\n";
            if( pr(2.0) % 2) {
                objects.push_back(
                    reinterpret_cast<Object*>(
                        new Circle( { pr(1.0, 20.0), pr(1.0, 20.0) },
                                    pr(1.0, 20.0) )
                     )
                );
            } else {
                objects.push_back(
                    reinterpret_cast<Object*>(
                        new Circle( { pr(1.0, 20.0), pr(1.0, 20.0) },
                                    { pr(1.0, 20.0), pr(1.0, 20.0) } )
                    )
                );
            }
            break;


        case 2:
            std::cout << "Rectangle.\n";
            objects.push_back(
                reinterpret_cast<Object*>(
                    new Rectangle( { pr(1.0, 20.0), pr(1.0, 20.0) },
                                   pr(5.0, 10.0),
                                   pr(10.5, 20.0) )
                 )
            );
            break;

        case 3:
            std::cout << "Rectangle.\n";
            objects.push_back(
                reinterpret_cast<Object*>(
                    new Square( { pr(1.0, 20.0), pr(1.0, 20.0) },
                                pr(5.0, 10.0) )
                 )
            );
            break;

        default:
            break;
        }
    }// end for

    std::cout << "\nBEGIN\n";

    std::for_each(objects.begin(),
                  objects.end(),
                  std::mem_fn(&Object::render));

    std::cout << "\nEND\n";

    for (auto* e : objects) {
        delete e;
    }
}

Example output:
Creating random Point.
Creating random Rectangle.
Creating random Rectangle.
Creating random Rectangle.
Creating random Circle.
Creating random Circle.
Creating random Rectangle.
Creating random Circle.
Creating random Rectangle.
Creating random Rectangle.

BEGIN

Point (16.6758 , 2.66872)

Rectangle:
upper-left: (2.76007 , 14.7382); upper-right: (7.82015 , 14.7382)
bottom-right: (7.82015 , 19.7982); bottom-left: (2.76007 , 19.7982)
base: 5.06008; height: 5.06008; diagonal: 7.15604

Rectangle:
upper-left: (-1.34479 , 3.67283); upper-right: (5.0166 , 3.67283)
bottom-right: (5.0166 , 10.0342); bottom-left: (-1.34479 , 10.0342)
base: 6.36139; height: 6.36139; diagonal: 8.99637

Rectangle:
upper-left: (-3.82646 , 8.7972); upper-right: (14.0239 , 8.7972)
bottom-right: (14.0239 , 16.8824); bottom-left: (-3.82646 , 16.8824)
base: 17.8504; height: 8.08522; diagonal: 19.5961

Circle: centre is (17.735 , 16.3054) and radius is 4.32386

Circle: centre is (17.4648 , 6.60121) and radius is 7.23713

Rectangle:
upper-left: (-0.996065 , 0.192477); upper-right: (6.68069 , 0.192477)
bottom-right: (6.68069 , 7.86923); bottom-left: (-0.996065 , 7.86923)
base: 7.67675; height: 7.67675; diagonal: 10.8566

Circle: centre is (2.40745 , 14.2627) and radius is 19.8776

Rectangle:
upper-left: (7.97622 , 2.64827); upper-right: (16.8076 , 2.64827)
bottom-right: (16.8076 , 11.4797); bottom-left: (7.97622 , 11.4797)
base: 8.8314; height: 8.8314; diagonal: 12.4895

Rectangle:
upper-left: (4.04397 , -1.57335); upper-right: (11.5453 , -1.57335)
bottom-right: (11.5453 , 5.92803); bottom-left: (4.04397 , 5.92803)
base: 7.50138; height: 7.50138; diagonal: 10.6085

END

Topic archived. No new replies allowed.