Compiler told me that it cannot find copy constructor but I declared and implemented it for both class Lin and Point... What I did wrong...
Many thanks in advance !
1>------ Build started: Project: Exercise 3 Variant, Configuration: Debug Win32 ------
1> main.cpp
1>c:\program files\boost\boost_1_47\boost\variant\detail\initializer.hpp(95): error C2558: class 'Line' : no copy constructor available or copy constructor is declared 'explicit'
1> c:\program files\boost\boost_1_47\boost\variant\detail\initializer.hpp(90) : while compiling class template member function 'int boost:etail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize(void *,const Line &)'
1> with
1> [
1> BaseIndexPair=boost::mpl:air<boost:etail::variant::make_initializer_node::apply<boost::mpl:air<boost:etail::variant::initializer_root,boost::mpl::int_<0>>,boost::mpl::l_iter<boost::mpl::list2<Point,Line>>>::initializer_node,boost::mpl::int_<1>>,
1> Iterator=boost::mpl::l_iter<boost::mpl::list1<Line>>
1> ]
1> c:\program files\boost\boost_1_47\boost\variant\variant.hpp(1208) : see reference to class template instantiation 'boost:etail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node' being compiled
1> with
1> [
1> BaseIndexPair=boost::mpl:air<boost:etail::variant::make_initializer_node::apply<boost::mpl:air<boost:etail::variant::initializer_root,boost::mpl::int_<0>>,boost::mpl::l_iter<boost::mpl::list2<Point,Line>>>::initializer_node,boost::mpl::int_<1>>,
1> Iterator=boost::mpl::l_iter<boost::mpl::list1<Line>>
1> ]
1> c:\program files\boost\boost_1_47\boost\variant\variant.hpp(1327) : see reference to class template instantiation 'boost::variant<T0_,T1>::initializer' being compiled
1> with
1> [
1> T0_=Point,
1> T1=Line
1> ]
1> c:\program files\boost\boost_1_47\boost\variant\variant.hpp(1399) : see reference to function template instantiation 'void boost::variant<T0_,T1>::convert_construct<const T>(T &,int,boost::mpl::false_)' being compiled
1> with
1> [
1> T0_=Point,
1> T1=Line,
1> T=Point
1> ]
1> c:\all my\с++\ha level 8\solution\level 8\exercise 3 variant\main.cpp(28) : see reference to function template instantiation 'boost::variant<T0_,T1>::variant<Point>(const T &)' being compiled
1> with
1> [
1> T0_=Point,
1> T1=Line,
1> T=Point
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Code:
//line.h
#ifndef LINE_H
#define LINE_H
#include "Shape.h"
#include "Point.h"
#include <string>
#include <iostream>
using namespace std;
class Line : public Shape
{
private:
Point start;
string discrib;
Point end;
public:
//constructors and destructor
Line();
Line(string x, Point P_start, Point P_end);
Line(Line& line); // line copy constructor
~Line();
//getters and setters
void SetStart ( Point SomePoint);
void SetEnd ( Point SomePoint);
Point GetStart() ;
Point GetEnd() ;
Line operator = ( Line& l);
// friend ostream& operator << (ostream& os , const Line& l);
//other useful methods
void ToString();
};
#endif
//point.h
#ifndef POINT_H
#define POINT_H
#include "Shape.h"
#include <iostream>
#include <string>
using namespace std;
class Point : public Shape
{
private:
double Xcoord;
double Ycoord;
public:
Point();
Point (double xNew, double yNew);
Point( Point& point); // copy constructor for Point
~Point();
void X( double Value);
void Y( double Value);
double X() ;
double Y() ;
Point operator = ( Point& p);
friend ostream& operator << (ostream& os , Point& p);
void ToString();
};
#endif
// shape.h
#ifndef Shape_h
#define Shape_h
#include <iostream>
#include "stdlib.h"
#include "Shape.h"
using namespace std;
class Shape
{
protected:
int m_id; // Add a data member for an id number of type int.
public:
int id;
int ID(); // return n_id data
Shape(); // initialises the id using a random number
Shape(const Shape &OtherShape); // copies the id member
Shape operator = (const Shape &OtherShape); // copies the id member
virtual void ToString() ; // returns the id as string e.g. “ID: 123”
};
#endif
//line.cpp
#include <iostream>
//#include <math.h>
#include "line.h"
#include "Point.h"
#include "Shape.h"
#include <string>
using namespace std;
Line::Line(){}
Line::Line(string x, Point P_start, Point P_end)
:discrib(x), start(P_start), end(P_end) {}
Line::Line( Line& line)
{
start = line.start;
end = line.end;
}
Line::~Line() {}
void Line::SetStart( Point SomePoint)
{
start = SomePoint;
}
void Line::SetEnd ( Point SomePoint)
{
end = SomePoint;
}
Point Line::GetStart()
{
return start;
}
Point Line::GetEnd()
{
return end;
}
Line Line::operator = ( Line& l)
{
if (this == &l)
{
return * this;
}
/*member function from base class */
m_id = l.m_id;
/* data from derived class*/
discrib = l.discrib;
start = l.start;
end = l.end;
return *this ;
}
void Line::ToString() // returns the line as string
{
cout << "[[" << discrib << ","
<< start << "," << end << "]]" << endl;
}
//Point.cpp
#include <iostream>
#include "Point.h"
using namespace std;
Point::Point() {}
Point::Point (double xNew, double yNew)
: Xcoord(xNew), Ycoord(yNew) {}
Point::~Point() {} //Destructor
Point::Point( Point& point) // Point copy constructor
{
Xcoord = point.Xcoord;
Ycoord = point.Ycoord;
}
void Point::X( double Value)
{//Assign X-coordinate the Value that is put into the main
Xcoord = Value;
}
void Point::Y( double Value)
{//Assing Y-coordinate the Value that is put into the main
Ycoord = Value;
}
double Point::X()
{
return Xcoord;//Return X-coordinate
}
double Point::Y()
{
return Ycoord;//Return Y-coordinate
}
void Point::ToString()
{
cout << "( " << X() << ","
<< Y() << " )";
}
Point Point::operator = ( Point& p)
{
if (this == &p)
{
return * this;
}
m_id = p.m_id;// member function from base class
Xcoord = p.Xcoord;// data from derived class
Ycoord = p.Ycoord;
return *this;
}
ostream& operator << (ostream& os , Point& p)
{
os << "[" << p.X() << "," << p.Y() << "]";
return os ;
}
//Shape.cpp
#include <iostream>
#include "Shape.h"
using namespace std;
Shape::Shape() // initialises the id using a random number
{
m_id = rand();
///cout << "id of shape is: " << m_id << endl;
}
int Shape::ID() // retrieve the id of the shape
{
return m_id;
}
void Shape::ToString() // returns the id as string
{
// cout << "ID: "<< ID();
}
Shape::Shape(const Shape &OtherShape)
{//copy constructor that copies the id member
id = OtherShape.m_id;
}
Shape Shape::operator = (const Shape& OtherShape)
{//assignment operator that copies the id member
if (this == &OtherShape)
{
return *this;
}
m_id = OtherShape.m_id;
return *this;
}
//main.cpp
//Variant
#include "Point.h"//header file declaration of class Point
#include "Line.h"//header file declaration of class Line
//#include "Circle.h"//header file declaration of class Circle
#include "Shape.h"//header file declaration of class Shape
#include <boost/variant.hpp>//includes boost class for variant
#include <iostream>// C++ style I/O using operator overloading
#include <ostream>
using namespace std;// The C++ logical collection of functions
//defines a shape type that can be of the form Point, Line or Circle
typedef boost::variant<Point, Line/*, Circle*/> ShapeType;
//function that returns a variant with the specified shape
ShapeType shape_type(){
int type;//selector variable
cout<<"Please enter 1 for shape of Point type"<<endl;
cout<<"Please enter 2 for shape of Line type"<<endl;
//cout<<"Please enter 3 for shape of Circle type"<<endl;
cin>>type;
//assigns the user given type to the variant
if(type==1){//creates a point and returns it
return Point();
}
else if(type==2){//creates a line and returns it
return Line();
}
/*else if(type==3){//creates a circle and returns it
return Circle();
}*/
}
//Visitor class
class VisitorClass: public boost::static_visitor<void>{
private:
double m_dx;//x delta to move
double m_dy;//y delta to move
public:
//==================================================================================================
//modifiers
//==================================================================================================
//function that Visits a point and moves its X,Y values
VisitorClass(double xval,double yval):m_dx(xval),m_dy(yval){
}
void operator()(Point& p) const{
//modifies the values of the point according to the user given inputs
p.X(p.X()+m_dx);
p.Y(p.Y()+m_dy);
}
//function that Visits a Line and moves its X,Y values of the starting and ending points
void operator()(Line& l) const{
//modifies the values of the starting point according to the user given inputs
//l.p1().X(l.p1().X()+m_dx);
//l.p1().Y(l.p1().Y()+m_dy);
l.GetStart().X(l.GetStart().X()+m_dx);
l.GetStart().Y(l.GetStart().Y()+m_dx);
//modifies the values of the ending point according to the user given inputs (scaled by 2)
//l.p2().X(l.p2().X()+m_dx*2);
//l.p2().Y(l.p2().Y()+m_dy*2);
l.GetEnd().X(l.GetEnd().X()+m_dx*2);
l.GetEnd().Y(l.GetEnd().Y()+m_dy*2);
}
//function that Visits a Circle and moves its X,Y values of its center
/*void operator()(Circle& c) const{
//modifies the values of the center point with the user given values
c.centerPoint().X((c.centerPoint().X()+m_dx));
c.centerPoint().Y((c.centerPoint().Y()+m_dy));
c.radius(m_dx+m_dy);
}*/
};
int main(){
//========================================================================================================================
// usage of variant data container
//========================================================================================================================
//Assigns a shape type via shape_type function
ShapeType figure=shape_type();
//prints the type of the figure given by the user
const std::type_info &ti=figure.type();//captures the type
cout<<"The created figure type is an object of the "<<ti.name()<<endl;//calls its names and prints it
cout<<figure;//the user assignation is sent to the cout using the overloaded << operator in each shape class
Line l("MyLine",Point(3,4),Point(6,8));//creates a Line
try{
boost::get<Line>(figure)=l;//assigns Line l to the figure variant
}
catch(boost::bad_get e){
std::cout << "***********************bad get error**************************" <<std::endl;
}
boost::apply_visitor(VisitorClass(9,12),figure);//shifts the figure according to a user given values
cout<<figure;//the user assignation is sent to the cout.
return 0;
}
My project compile now but something going wrong , please help
I attached two print screen
first, is about if I choose Line class
second, if I choose Point... This one very bad((( Even go to exception (((
Many thanks in advance
Code:
//line.h
#ifndef LINE_H
#define LINE_H
#include "Shape.h"
#include "Point.h"
#include <string>
#include <iostream>
using namespace std;
class Line : public Shape
{
private:
Point start;
Point end;
public:
//constructors and destructor
Line();
Line(Point P_start, Point P_end);
Line(const Line& line) ; // line copy constructor
~Line();
//getters and setters
void SetStart ( Point SomePoint);
void SetEnd ( Point SomePoint);
Point GetStart() const ;
Point GetEnd() const;
Line operator = (const Line& l) ; //
friend ostream& operator << (ostream& os , const Line& l);
//other useful methods
void ToString();
};
#endif
//point.h
#ifndef POINT_H
#define POINT_H
#include "Shape.h"
#include <iostream>
#include <string>
using namespace std;
class Point : public Shape
{
private:
double Xcoord;
double Ycoord;
public:
Point();
Point (double xNew, double yNew);
Point(const Point& point); // copy constructor for Point
~Point();
void X( double Value);
void Y( double Value);
double X() const ;
double Y() const ;
Point operator = (const Point& p); // for Point class
friend ostream& operator << ( ostream& os ,const Point& p);
void ToString();
};
#endif
// shape.h
#ifndef Shape_h
#define Shape_h
#include <iostream>
#include "stdlib.h"
#include "Shape.h"
using namespace std;
class Shape
{
protected:
int m_id; // Add a data member for an id number of type int.
public:
int id;
int ID(); // return n_id data
Shape(); // initialises the id using a random number
Shape(const Shape &OtherShape); // copies the id member
Shape operator = (const Shape &OtherShape); // copies the id member
virtual void ToString() ; // returns the id as string e.g. “ID: 123”
};
#endif
//line.cpp
#include <iostream>
//#include <math.h>
#include "line.h"
#include "Point.h"
#include "Shape.h"
#include <string>
using namespace std;
Line::Line(){}
Line::Line(Point P_start, Point P_end)
: start(P_start), end(P_end) {}
Line::Line(const Line& line)
{
start = line.start;
end = line.end;
}
Line Line::operator = (const Line& l)
{
if (this == &l)
{
return * this;
}
/*member function from base class */
m_id = l.m_id;
/* data from derived class*/
start = l.start;
end = l.end;
return *this ;
}
Line::~Line() {}
void Line::SetStart( Point SomePoint)
{
start = SomePoint;
}
void Line::SetEnd ( Point SomePoint)
{
end = SomePoint;
}
Point Line::GetStart() const
{
return start;
}
Point Line::GetEnd() const
{
return end;
}
ostream& operator << ( ostream& os , const Line& l)
{
os << "[" << l.GetStart() << "," << l.GetEnd() << "]";
return os ;
}
void Line::ToString() // returns the line as string
{
cout << "[["
<< start << "," << end << "]]" << endl;
}
//Point.cpp
#include <iostream>
#include "Point.h"
using namespace std;
Point::Point() {}
Point::Point (double xNew, double yNew)
: Xcoord(xNew), Ycoord(yNew) {}
Point::~Point() {} //Destructor
Point::Point(const Point& point) // Point copy constructor
{
Xcoord = point.Xcoord;
Ycoord = point.Ycoord;
}
void Point::X( double Value)
{//Assign X-coordinate the Value that is put into the main
Xcoord = Value;
}
void Point::Y( double Value)
{//Assing Y-coordinate the Value that is put into the main
Ycoord = Value;
}
double Point::X() const
{
return Xcoord;//Return X-coordinate
}
double Point::Y() const
{
return Ycoord;//Return Y-coordinate
}
void Point::ToString()
{
cout << "( " << X() << ","
<< Y() << " )";
}
Point Point::operator = (const Point& p)
{
if (this == &p)
{
return * this;
}
m_id = p.m_id;// member function from base class
Xcoord = p.Xcoord;// data from derived class
Ycoord = p.Ycoord;
return *this;
}
ostream& operator << ( ostream& os , const Point& p)
{
os << "[" << p.X() << "," << p.Y() << "]";
return os ;
}
//Shape.cpp
#include <iostream>
#include "Shape.h"
using namespace std;
Shape::Shape() // initialises the id using a random number
{
m_id = rand();
///cout << "id of shape is: " << m_id << endl;
}
int Shape::ID() // retrieve the id of the shape
{
return m_id;
}
void Shape::ToString() // returns the id as string
{
// cout << "ID: "<< ID();
}
Shape::Shape(const Shape &OtherShape)
{//copy constructor that copies the id member
id = OtherShape.m_id;
}
Shape Shape::operator = (const Shape& OtherShape)
{//assignment operator that copies the id member
if (this == &OtherShape)
{
return *this;
}
m_id = OtherShape.m_id;
return *this;
}
//main.cpp
//Variant
#include "Point.h"//header file declaration of class Point
#include "Line.h"//header file declaration of class Line
//#include "Circle.h"//header file declaration of class Circle
#include "Shape.h"//header file declaration of class Shape
#include <boost/variant.hpp>//includes boost class for variant
#include <iostream>// C++ style I/O using operator overloading
#include <ostream>
using namespace std;// The C++ logical collection of functions
//defines a shape type that can be of the form Point, Line or Circle
typedef boost::variant<Point, Line/*, Circle*/> ShapeType;
//function that returns a variant with the specified shape
ShapeType shape_type(){
int type;//selector variable
cout<<"Please enter 1 for shape of Point type"<<endl;
cout<<"Please enter 2 for shape of Line type"<<endl;
//cout<<"Please enter 3 for shape of Circle type"<<endl;
cin>>type;
//assigns the user given type to the variant
if(type==1){//creates a point and returns it
return Point();
}
else if(type==2){//creates a line and returns it
return Line();
}
/*else if(type==3){//creates a circle and returns it
return Circle();
}*/
}
//Visitor class
class VisitorClass: public boost::static_visitor<void>{
private:
double m_dx;//x delta to move
double m_dy;//y delta to move
public:
//==================================================================================================
//modifiers
//==================================================================================================
//function that Visits a point and moves its X,Y values
VisitorClass(double xval,double yval):m_dx(xval),m_dy(yval){
}
void operator()(Point& p) const{
//modifies the values of the point according to the user given inputs
p.X(p.X()+m_dx);
p.Y(p.Y()+m_dy);
}
//function that Visits a Line and moves its X,Y values of the starting and ending points
void operator()(Line& l) const{
//modifies the values of the starting point according to the user given inputs
//l.p1().X(l.p1().X()+m_dx);
//l.p1().Y(l.p1().Y()+m_dy);
l.GetStart().X(l.GetStart().X()+m_dx);
l.GetStart().Y(l.GetStart().Y()+m_dx);
//modifies the values of the ending point according to the user given inputs (scaled by 2)
//l.p2().X(l.p2().X()+m_dx*2);
//l.p2().Y(l.p2().Y()+m_dy*2);
l.GetEnd().X(l.GetEnd().X()+m_dx*2);
l.GetEnd().Y(l.GetEnd().Y()+m_dy*2);
}
//function that Visits a Circle and moves its X,Y values of its center
/*void operator()(Circle& c) const{
//modifies the values of the center point with the user given values
c.centerPoint().X((c.centerPoint().X()+m_dx));
c.centerPoint().Y((c.centerPoint().Y()+m_dy));
c.radius(m_dx+m_dy);
}*/
};
int main(){
//========================================================================================================================
// usage of variant data container
//========================================================================================================================
//Assigns a shape type via shape_type function
ShapeType figure=shape_type();
//prints the type of the figure given by the user
const std::type_info &ti=figure.type();//captures the type
cout<<"The created figure type is an object of the "<<ti.name()<<endl;//calls its names and prints it
cout<<figure;//the user assignation is sent to the cout using the overloaded << operator in each shape class
Line l(Point(3,4),Point(6,8));//creates a Line
try{
boost::get<Line>(figure)=l;//assigns Line l to the figure variant
}
catch(boost::bad_get e){
std::cout << "***********************bad get error**************************" <<std::endl;
}
boost::apply_visitor(VisitorClass(9,12),figure);//shifts the figure according to a user given values
cout<<figure;//the user assignation is sent to the cout.
return 0;
}
My project compile now but something going wrong , please help
I attached two print screen
1) Please format your code so that it's properly indented and readable. You keep posting code that is formatted all over the place, making it very difficult to read.
2) Quit writing functions that are totally unnecessary. Why are you writing user-defined copy constructors and assignment operators for your classes? The default ones are perfectly acceptable -- you don't need to write any of these functions. If you keep writing functions that are unnecessary, all that does is make it easier for bugs to occur.
3) Why are you not debugging your code? Programming is more than just writing code, running it, and if something goes wrong, post a message on CodeGuru. You have to show that you've made the attempt to debug your code yourself.
4) Post each file in separate code blocks. Mushing everything into one huge code block makes it very difficult to see what's going on.
First, take each class. All of them have either mistakes, unnecessary includes/code:
Shape.h
Code:
#ifndef Shape_h
#define Shape_h
class Shape
{
protected:
int m_id; // Add a data member for an id number of type int.
public:
int id; // what is this for??
int ID() const;
Shape();
virtual void ToString();
virtual ~Shape() {}
};
#endif
1) Note that there are no includes, because nothing in that file uses anything in <string> or any other header you used. In your original file, you were including "Shape.h" inside of shape.h. Why were you doing this? For Windows, that results in a circular include, resulting in the code not compiling.
2) You are deriving from Shape, therefore it needs to have a virtual destructor. Do you know why a virtual destructor is needed for Shape? If not, there are plenty of explanations of this, and I just don't have the time to repost why you need one.
3) Why is there an id member variable?
4) The copy constructor and assignment operator, and destructor have been removed. Again, there is no need to write these functions.
I didn't compile all of this, but the point is that the code is simpler. There are no copy constructors or assignment operators to mess up or other unnecessary functions.
The next step for you is to take a simple main() program that uses the boost classes and make sure you know how to use them before you write or call other functions that do something much more complex. If you believe you can use boost::any correctly and call of these visitor pattern functions, then there really isn't any need for you to ask us to debug your code, since these items assume you're an intermediate to advanced C++ programmer.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; July 4th, 2012 at 12:56 PM.
Note that if you're following Paul McKenzie's examples, you will find that you don't need operator<< to be a friend. Furthermore, ToString does not need to be a member since you can call the GetStart and GetEnd member functions instead of accessing the member variables directly.
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar
I didn't compile all of this, but the point is that the code is simpler. There are no copy constructors or assignment operators to mess up or other unnecessary functions.
The next step for you is to take a simple main() program that uses the boost classes and make sure you know how to use them before you write or call other functions that do something much more complex. If you believe you can use boost::any correctly and call of these visitor pattern functions, then there really isn't any need for you to ask us to debug your code, since these items assume you're an intermediate to advanced C++ programmer.
Now everything fine with Point class but Line class don't work correctly. The problem is when I choice line class it gives me value that I set up in default constructor and don't change value after called visitor.
Now I set up in default constructor in Line class [(1,2) (3,1)]... but I need that code gives me value of MyLine [(3,4,) (6,8)]
What wrong with Line class
last edition:
Code:
[CPP]// line.h
#ifndef LINE_H
#define LINE_H
#include "Shape.h"
#include "Point.h"
#include <ostream>
class Line : public Shape
{
private:
Point start;
// string discrib;
Point end;
public:
//constructors and destructor
Line();
Line( Point& P_start, Point& P_end);
Line(const Line& line); // line copy constructor
~Line();
//getters and setters
void SetStart ( Point& SomePoint);
void SetEnd ( Point& SomePoint);
Point GetStart() const ;
Point GetEnd() const ;
Line& operator = ( const Line& l);
friend ostream& operator << (ostream& os , const Line& l);
//other useful methods
void ToString() const;
};
#endif
//point.h
#ifndef POINT_H
#define POINT_H
#include "Shape.h"
#include <ostream>
class Point : public Shape
{
private:
double Xcoord;
double Ycoord;
public:
Point();
Point (double xNew, double yNew);
Point( const Point& point); // copy constructor for Point
~Point();
void X( double Value);
void Y( double Value);
double X() const;
double Y() const;
Point& operator = ( const Point& p);
friend ostream& operator << (ostream& os , const Point& p);
void ToString() const;
};
#endif
#ifndef Shape_h
#define Shape_h
#include <string>
#include <iostream>
using namespace std;
// shape.h
class Shape
{
protected:
int m_id; // Add a data member for an id number of type int.
public:
int id;
int ID() const; // return n_id data
Shape(); // initialises the id using a random number
Shape(const Shape &OtherShape); // copies the id member
Shape& operator = (const Shape &OtherShape); // copies the id member
virtual void ToString() const ; // returns the id as string e.g. “ID: 123”
};
#endif
//line.cpp
#include <iostream>
#include "line.h"
using namespace std;
Line::Line():start(Point(1, 2)), end(Point(3, 1)){}
Line::Line( Point& P_start, Point& P_end)
: start(P_start), end(P_end) {}
Line::Line( const Line& line)
{
start = line.start;
end = line.end;
}
Line::~Line() {}
void Line::SetStart( Point& SomePoint)
{
start = SomePoint;
}
void Line::SetEnd ( Point& SomePoint)
{
end = SomePoint;
}
Point Line::GetStart() const
{
return start;
}
Point Line::GetEnd() const
{
return end;
}
Line& Line::operator = ( const Line& l)
{
if (this == &l)
{
return * this;
}
/*member function from base class */
m_id = l.m_id;
/* data from derived class*/
start = l.start;
end = l.end;
return *this ;
}
void Line::ToString() const // returns the line as string
{
cout << "[["
<< start << "," << end << "]]" << endl;
}
ostream& operator << ( ostream& os , const Line& l)
{
os << "[" << l.GetStart() << "," << l.GetEnd() << "]";
return os ;
}
//Point.cpp
#include <iostream>
#include "Point.h"
using namespace std;
Point::Point() : Xcoord(0), Ycoord(0) {}
Point::Point (double xNew, double yNew)
: Xcoord(xNew), Ycoord(yNew) {}
Point::~Point() {} //Destructor
Point::Point( const Point& point) // Point copy constructor
{
Xcoord = point.Xcoord;
Ycoord = point.Ycoord;
}
void Point::X( double Value)
{//Assign X-coordinate the Value that is put into the main
Xcoord = Value;
}
void Point::Y( double Value)
{//Assing Y-coordinate the Value that is put into the main
Ycoord = Value;
}
double Point::X() const
{
return Xcoord;//Return X-coordinate
}
double Point::Y() const
{
return Ycoord;//Return Y-coordinate
}
void Point::ToString() const
{
cout << "( " << X() << ","
<< Y() << " )";
}
Point& Point::operator = ( const Point& p)
{
if (this == &p)
{
return * this;
}
m_id = p.m_id;// member function from base class
Xcoord = p.Xcoord;// data from derived class
Ycoord = p.Ycoord;
return *this;
}
ostream& operator << (ostream& os , const Point& p)
{
os << "[" << p.X() << "," << p.Y() << "]";
return os ;
}
//Shape.cpp
#include <iostream>
#include "Shape.h"
//using namespace std;
Shape::Shape() // initialises the id using a random number
{
m_id = rand();
///cout << "id of shape is: " << m_id << endl;
}
int Shape::ID() const // retrieve the id of the shape
{
return m_id;
}
void Shape::ToString() const// returns the id as string
{
// cout << "ID: "<< ID();
}
Shape::Shape(const Shape &OtherShape)
{//copy constructor that copies the id member
id = OtherShape.m_id;
}
Shape& Shape::operator = (const Shape& OtherShape)
{//assignment operator that copies the id member
if (this == &OtherShape)
{
return *this;
}
m_id = OtherShape.m_id;
return *this;
}
//main.cpp
#include "Point.h" //header file declaration of class Point
#include "Line.h" //header file declaration of class Line
//#include "Circle.h" //header file declaration of class Circle
#include "Shape.h" //header file declaration of class Shape
#include <boost/variant.hpp> //includes boost class for variant
#include <iostream> // C++ style I/O using operator overloading
#include <ostream>
using namespace std; // The C++ logical collection of functions
//defines a shape type that can be of the form Point, Line or Circle
typedef boost::variant<Point, Line/*, Circle*/> ShapeType;
//function that returns a variant with the specified shape
ShapeType shape_type()
{
int type;//selector variable
cout<<"Please enter 1 for shape of Point type"<<endl;
cout<<"Please enter 2 for shape of Line type"<<endl;
//cout<<"Please enter 3 for shape of Circle type"<<endl;
cin>>type;
//assigns the user given type to the variant
if(type==1)
{ //creates a point and returns it
return Point();
}
else if(type==2)
{ //creates a line and returns it
return Line();
}
/*else if(type==3){//creates a circle and returns it
return Circle();
}*/
}
//Visitor class
class VisitorClass: public boost::static_visitor<void>
{
private:
double m_dx;//x delta to move
double m_dy;//y delta to move
public:
//==================================================================================================
//modifiers
//==================================================================================================
//function that Visits a point and moves its X,Y values
VisitorClass(double xval,double yval):m_dx(xval),m_dy(yval) {}
void operator()(Point& p) const
{
//modifies the values of the point according to the user given inputs
p.X(p.X()+m_dx);
p.Y(p.Y()+m_dy);
}
//function that Visits a Line and moves its X,Y values of the starting and ending points
void operator()(Line& l) const
{
//modifies the values of the starting point according to the user given inputs
//l.p1().X(l.p1().X()+m_dx);
//l.p1().Y(l.p1().Y()+m_dy);
//l.GetStart().X(l.GetStart().X()+m_dx);
//l.GetStart().Y(l.GetStart().Y()+m_dx);
l.GetStart().X(l.GetStart().X()+m_dx);
l.GetStart().Y(l.GetStart().Y()+m_dx);
//modifies the values of the ending point according to the user given inputs (scaled by 2)
//l.p2().X(l.p2().X()+m_dx*2);
//l.p2().Y(l.p2().Y()+m_dy*2);
l.GetEnd().X(l.GetEnd().X()+m_dx*2);
l.GetEnd().Y(l.GetEnd().Y()+m_dy*2);
}
//function that Visits a Circle and moves its X,Y values of its center
/*void operator()(Circle& c) const{
//modifies the values of the center point with the user given values
c.centerPoint().X((c.centerPoint().X()+m_dx));
c.centerPoint().Y((c.centerPoint().Y()+m_dy));
c.radius(m_dx+m_dy);
}*/
};
int main(){
//========================================================================================================================
// usage of variant data container
//========================================================================================================================
Point p(11,1);
Point p1(2,2);
Point p2(3,3);
Line l(Point(3,4),Point(6,8));
//Assigns a shape type via shape_type function
ShapeType figure=shape_type();
cout << "\n\n\t myLine" << l << "\n\n\t";
try
{
switch (figure.which())
{
case 0: cout << "\n\n\tPoint"; break;
case 1: cout << "\n\n\tLine"; break;
default : cout << "invalide input" ;
}
//the user assignation is sent to the cout using the overloaded << operator in each shape class
//creates a Line
boost::get<Point>(figure)=p;//assigns Line l to the figure variant
boost::get<Line>(figure)=l;//assigns Line l to the figure variant
}
catch(boost::bad_get e)
{
std::cout << "\n\n\t***********************bad get error**************************" <<std::endl;
}
cout<<"\n\n\t BEFORE VISITOR "<< figure << "\n\n\t ";
boost::apply_visitor(VisitorClass(9,12),figure);//shifts the figure according to a user given values
cout<<"\n\n\t AFTER VISITOR "<<figure;//the user assignation is sent to the cout.
cout << "\n\n\t";
system ("pause");
return 0;
}[/CPP]
You are now in trouble, since you did not take care of the base class. In other words, you have a bogus copy of the Line class because Shape was not copied.
Then you have this:
Code:
Line& Line::operator = ( const Line& l)
{
if (this == &l)
{
return * this;
}
/*member function from base class */
m_id = l.m_id;
/* data from derived class*/
start = l.start;
end = l.end;
return *this ;
}
So what happens if Shape changes and adds a member variable? You now have to change this too. You cannot assume what "Shape" has as member variables.
The bottom line is that you don't need to write these functions at all for the classes you have. All of the members are safely copyable by themselves without you having to do anything. So really, get rid of these functions..
Let me ask you -- do you know what the compiler generated copy constructor and assignment operator do? If you did know, you would know that you don't need to write these functions yourself. The compiler generated version will never get this wrong, so let the compiler handle the copying. By you telling the compiler that you can write your own copy constructors and assignment operators, all the responsibility of writing them correctly is yours, and you failed.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; July 22nd, 2012 at 10:46 AM.
You are now in trouble, since you did not take care of the base class. In other words, you have a bogus copy of the Line class because Shape was not copied.
Then you have this:
Code:
Line& Line::operator = ( const Line& l)
{
if (this == &l)
{
return * this;
}
/*member function from base class */
m_id = l.m_id;
/* data from derived class*/
start = l.start;
end = l.end;
return *this ;
}
So what happens if Shape changes and adds a member variable? You now have to change this too. You cannot assume what "Shape" has as member variables.
The bottom line is that you don't need to write these functions at all for the classes you have. All of the members are safely copyable by themselves without you having to do anything. So really, get rid of these functions..
Let me ask you -- do you know what the compiler generated copy constructor and assignment operator do? If you did know, you would know that you don't need to write these functions yourself. The compiler generated version will never get this wrong, so let the compiler handle the copying. By you telling the compiler that you can write your own copy constructors and assignment operators, all the responsibility of writing them correctly is yours, and you failed.
Regards,
Paul McKenzie
I not quit understand your idea... What should I do to resolve my problem belong Line class
About your idea you try to say that I should add to Shape class data member function that will be inherent by Point or Line class ?
or You mean that I should make explicit inheritance between derived and base classes constructors
I not quit understand your idea... What should I do to resolve my problem belong Line class
Again, get out of the business of writing copy constructors and assignment operators. There is no need for you to write these functions at all. This is for all of your classes.
I'll answer you, just for your information. The reason why the Line copy constructor is wrong is this: you are taking an existing Line object and copying it to a new Line object. That existing Line object has a base class Shape. That Shape part of the Line object needs to be copied too -- if not, you get a new Line object with some members set correctly, but the base class members set incorrectly.
When you copy, you must copy everything from the existing object. This includes invoking the base class copy constructor. Look at this simple example:
Code:
class Base
{
int m_x;
public:
Base(int x = 0 ) : m_x(x) { }
};
class Derived : public Base
{
int m_d;
public:
Derived(int d) : m_d(d), Base(d) { }
// Now let me try to outsmart the compiler and write my own (wrong) copy ctor
Derived(const Derived& obj)
{
m_d = obj.m_d;
}
};
int main()
{
Derived d1(10);
Derived d2(d1); // you're in trouble
}
The reason why the second line in main() causes a problem is that d2 will have m_d set, but what about the m_x (the member in the base class)? When I run the code above, d2 has its m_x member set to 0, but in d1, m_x it is set to 10. So d2 is not equal to d1 -- you don't have a real copy, you have a "half-copy" masquerading as a real copy.
These errors are some of the hardest to find when your program starts running. In the example above, if I were to use d2 assuming that it is an exact copy of d1, my program will not run correctly. Now when you write functions that return objects by value, or you start to use other classes that use value types (for example any of the STL container classes), your wrong copy constructor messes up everything, things go haywire, and your program blows up.
The example above is exactly what you're doing with your Line copy constructor. So how do you fix it? The best way to fix it is to not write the copy constructor. Let the compiler do the copy -- the compiler will do it correctly, doesn't make mistakes, goes through all of the members (including ones in base classes) and makes the copies, etc. Why do you want to do this work yourself?
Assuming all of the members are safely copyable, what if your class had 50 member variables? Would you write the code to copy 50 members? How about 100 member variables? Won't you get tired at some point writing all of this code to make the copies? What if you forget to copy the 27th member variable (maybe your eyes got tired and missed it)? You now have a bug in your program because you missed copying that member variable. What if you have a class D, derived from class C, which is derived from class B, which is derived from class A? Are you going to go through all of those classes and write copy constructors and assignment operators, and then hoping you didn't miss anything when copying all of these objects?
The time when you need to code your own copy ctor and assignment operator is when the default compiler versions are not adequate. For example, if your class contains a pointer to dynamically allocated memory and you need to do a deep copy (the default versions only do shallow copies). But again, all of your classes you wrote Shape, Line, and Point have members that all they need are shallow copies, that's why you don't need to write these functions and instead let the compiler do the work for you.
But just for completeness, let's assume you did need to write a copy constructor. For the simple code I wrote above:
The same issue is the same with the assignment operator. You must make sure that the assignment of the base object is done so that you don't have bad copies, but again, there is no need to write assignment operators for the same reason there is no reason for you to write copy constructors.
or You mean that I should make explicit inheritance between derived and base classes constructors
BTW, then I comment out copy constructor or assignment operator from Line class compiler gives me linked error...
Then you didn't comment out all of the code concerning copy constructor and assignment operator .
All of the classes and structs that a C++ programmer writes have available copy constructors and assignment operators if these functions are not written by the programmer.. The only way for a copy constructor/assignment operator to give you a linker error is if you attempted to write your own copy assignment operator and you didn't implement it.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; July 22nd, 2012 at 09:22 PM.
But if you mean add new data member to Shape class why Point class works well ?
You made the same mistake as the Line class. Your Point class will not work "well" in anything but a toy program. If you don't believe me, copy a Point object to another Point object. You should see that the Shape part of the new Point object is incorrect.
You will have two Point objects that are not really copies of each other, but are saying to the whole world that they are copies. Somewhere in a real program, the lie that the two objects are real copies will crash a program, and you now have to spend sleepness nights finding and fxing that bug.
Secondly, never say "it works well" if you make mistakes like this -- you should know by now that if you have bugs in a C++ program like this, the behaviour of the program is undefined.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; July 22nd, 2012 at 05:46 PM.
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.