How can I declare a standard constructor in MFC that expects a CPoint argument, e.g.
class CObj {
public:
CObj(CPoint pt = ???, float x = 10.0f, int n = 10);
...
I tried
CObj(CPoint pt = (10,10), float x = 10.0f, int n = 10);
which compiled just fine, but only pt.x got the value 10 while pt.y became 0.
Thanks, RS
I believe something like this should work:
CObj(Cpoint pt = CPoint(10,10), float x = 10.0f, int n = 10);
Edit: It sure seems to work for me:
#include <iostream>
struct CPoint {
int x, y;
CPoint(int x_, int y_) : x(x_), y(y_) {}
};
class CObj {
CPoint p;
public:
CObj(CPoint pt = CPoint(10,10), float x = 10.0f, int n = 10) : p(pt) {
std::cout << "x.x = " << p.x << "\tx.y = " << p.y << std::endl;
}
};
int main() {
CObj x;
return 0;
}
Result:
x.x = 10 x.y = 10
Related
I am experimenting with lambda functions and managed to recreate a "get" functionality in C++. I can get the return value of a function without using parentheses. This is an example class, where I implement this:
using namespace std;
struct Vector2 {
float x;
float y;
float length = [&]()-> float {return sqrt(x * x + y * y); }();
float angle = [&]()-> float {return atan2(y, x); }();
Vector2() : x(0), y(0) {}
Vector2(float a, float b) : x(a), y(b) {}
~Vector2() {}
Vector2(Vector2& other) : x(other.x), y(other.y) {}
Vector2(Vector2&& other) = delete;
void operator =(Vector2&& other) noexcept{
x = other.x;
y = other.y;
}
};
int main()
{
Vector2 vec = Vector2(10, 17);
printf("%f\n%f\n%f\n%f\n", vec.x, vec.y, vec.length, vec.angle);
}
However, I am currently trying to also recreate the "set" functionality that C# has. But I'm failing. I tried to add this:
void angle = [&](float a)->void {
float l = length;
x = cos(a) * l;
y = sin(a) * l;
};
But am getting "Incomplete type is not allowed" error. I'm not sure if that's how it should look, even if I wasn't getting the error. Is it even possible to recreate the "set" functionality C# has in C++?
I know that I can just use a method SetAngle(float a){...}, but that's not really the point.
TL;DR: Don't
What you have isn't a getter, it's just a normal data member that's calculated once when the object is initialized.
In general, C++ doesn't support C#-style properties. The usual C++-style solution is to just use a pair of member functions (and maybe a data member, if you need to save the value separately), i.e.
struct Vector2 {
// ...
float length() const { return sqrt(x * x + y * y); }
void length(float l) {
float angle = angle();
float new_x = l * cos(angle);
float new_y = l * sin(angle);
x = new_x;
y = new_y;
}
// ...
};
You can get something close to a C#-style property, but you'll always run into edge-cases where they don't work perfectly. For example, here's something that will work in many cases:
template <typename T>
class Property
{
private:
std::function<T()> getter_;
std::function<void(const T&)> setter_;
public:
Property(std::function<T()> getter, std::function<void(const T&)> setter)
: getter_{getter},
setter_{setter}
{}
operator T()
{
return getter_();
}
const T& operator=(const T& val)
{
setter_(val);
return val;
}
};
struct Vector2
{
float x;
float y;
Property<float> length{
[this]() { return sqrt(x * x + y * y); },
[this](float l) {
float new_x = l * cos(angle);
float new_y = l * sin(angle);
x = new_x;
y = new_y;
}
}
Property<float> angle{
[this]() { return atan2(y, x); },
[this](float a) {
float l = length;
x = cos(a) * l;
y = sin(a) * l;
}
}
// ...
};
int main() {
Vector2 v;
v.x = 1;
v.y = 1;
v.angle = std::numbers::pi / 2;
std::cout << "(" << v.x << ", " << v.y << ")\n";
}
But this still falls apart in the edge cases, especially when you mix it with templates and/or auto type-deduction. For instance:
Vector2 v;
v.x = 1;
v.y = 1;
auto old_angle = v.angle;
v.angle = std::numbers::pi / 2;
// oops, this prints pi/2, not pi/4 like you probably expected
// because old_angle isn't a float, it's a Property<float> that
// references v
std::cout << old_angle << '\n';
Note also that there's a bug here. Consider this:
int main() {
Vector2 v1;
v1.x = 1;
v1.y = 1;
Vector2 v2 = v1;
v2.angle = std::numbers::pi / 2;
// Oops, assigning to v2.angle modified v1
std::cout << "(" << v1.x << ", " << v1.y << ")\n";
}
You could work around these issues by making Property non-copyable, but then you force any class that uses it to implement a custom copy-constructor. Also, while that would make the auto case "safe", it does so by turning it into a compile error. Still not ideal.
I agree with Miles. This is not the greatest idea, because it's unnatural for C++ developers, and you should write code that is first and foremost easy to read.
However, as an engineering challenge, here's a possible implementation:
#include <math.h>
#include <iostream>
template <typename T>
class Member
{
public:
operator T() const { return _value; }
void operator =(const T& value) const { _value = value; } void operator =(T&& value) { _value = std::move(value); }
private:
T _value;
};
class Angle
{
public:
Angle(const Member<float>& x, const Member<float>& y) :
_x(x), _y(y) {}
operator float() const { return atan2(_y, _x); }
private:
const Member<float>& _x, _y;
};
class Obj
{
public:
Member<float> x, y;
Angle angle;
Obj() : angle(this->x, this->y) {}
};
int main()
{
Obj o;
o.x = 3;
o.y = 5;
std::cout << o.x << ", " << o.y << " -> " << o.angle << std::endl;
}
While other solutions also seem to be possible, this one seems to be the most elegant :P
using namespace std;
struct Vector2 {
float x;
float y;
float init_length = [&]()-> float {return sqrt(x * x + y * y); }();
float init_angle = [&]()-> float {return atan2(y, x); }();
__declspec(property(get = GetAngle, put = SetAngle)) float angle;
__declspec(property(get = GetLength, put = SetLength)) float length;
Vector2() : x(0), y(0) {}
Vector2(float a, float b) : x(a), y(b) {}
~Vector2() {}
Vector2(Vector2& other) : x(other.x), y(other.y) {}
Vector2(Vector2&& other) = delete;
void operator =(Vector2&& other) = delete;
void Display() {
printf("%f\n%f\n%f\n%f\n\n", x, y, length, angle);
}
float GetLength() {
return sqrt(x * x + y * y);
}
float GetAngle() {
return atan2(y, x);
}
void SetLength(float l) {
float a = GetAngle();
x = cos(a) * l;
y = sin(a) * l;
}
void SetAngle(float a) {
float l = GetLength();
x = cos(a) * l;
y = sin(a) * l;
}
};
int main()
{
Vector2 vec = Vector2(10, 17);
vec.Display();
vec.length = 5;
vec.Display();
}
Fl_Multiline_Output* m_pLogOutput;
m_pLogOutput = new Fl_Multiline_Output(20, 330, 570, 530, "Log Output:");
m_pLogOutput->align(FL_ALIGN_TOP_LEFT);
I want to redirect any message printed to standard output (like std::cout << "Hello world") to appear on this m_pLogOutput. Is that possible?
Something like this - this example uses TextDisplay instead of MultiLineOutput. TextDisplay has scrollbars: MultilineOutput does not. This is written in FLTK2, calls are similar to FLTK1 without the FL_ and underscores between words.
It defines a class called ConOut. Note that you must not
#include <iostream>
since cout is redefined.
#include <fltk/run.h>
#include <fltk/ValueInput.h> // necessary for bug in mingw32?
#include <fltk/Window.h>
#include <fltk/Button.h>
#include <fltk/TextDisplay.h>
#include <sstream>
using namespace fltk;
class ConOut: public std::ostringstream
{
public:
ConOut& operator << (std::ostream&(*f)(std::ostream&))
{
if (f == std::endl)
{
*this << "\n";
std::string cumulative = control->text() + str();
control->text(cumulative.c_str());
str("");
}
else
{
// Don't worry about the warning
*this << f;
}
return *this;
}
void SetWidget(TextDisplay* in_control)
{
control = in_control;
}
TextDisplay* control;
template <typename T>
inline ConOut& operator << (const T& t)
{
(*(std::ostringstream*) this) << t;
return *this;
}
};
ConOut cout;
void cb_cauli(Widget*, void*)
{
cout << "Cauliflower" << std::endl;
}
void cb_brocolli(Widget*, void*)
{
cout << "Brocolli" << std::endl;
}
void cb_cabbage(Widget*, void*)
{
cout << "Cabbage" << std::endl;
}
int main(int argc, char **argv)
{
int btnw = 100, btnh = 30, bdr = 10;
int dlgw = bdr * 4 + 3 * btnw, dlgh = 200 + btnh + 3 * bdr, x, y, w, h;
Window * window = new Window(dlgw, dlgh);
window->begin();
// Create the multiline output
x = bdr;
y = bdr;
w = dlgw - 2 * bdr;
h = 200;
TextDisplay* text2 = new TextDisplay(x, y, w, h,"");
text2->clear_flag(fltk::ALIGN_MASK);
text2->set_flag(fltk::ALIGN_BOTTOM);
window->resizable(text2);
// Create the buttons which use cout
y += h + bdr;
w = btnw; h = btnh;
Button* cauli = new Button(x, y, w, h, "Cauliflower");
cauli->callback(cb_cauli);
x += w + bdr;
Button* brocolli = new Button(x, y, w, h, "Brocolli");
brocolli->callback(cb_brocolli);
x += w + bdr;
Button* cabbage = new Button(x, y, w, h, "Cabbage");
cabbage->callback(cb_cabbage);
// Set the widget for cout
cout.SetWidget(text2);
window->end();
window->show(argc,argv);
return fltk::run();
}
I am trying to figure out how to find the axis of class Square's axis as shown below? But I've been trying for hours and still did not managed to solve it. Can someone with their high level expertise show me the ropes to do it? Because both center function call and axis function call in main() does call the same x() and y(), hence brought me to a state of confusion. I know the inheritance of square from circle is weird. But it is what my school wants. Note: Main() CANNOT be modified! Thanks!
Output:
Square::axis test failed
8.87627 0.284967
3.82567 0.958537
Tests passed: 50%
#include <iostream>
#include <cstdlib>
#include <ctime>
#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;
}
};
struct VectorType
{
float tx;
float ty;
VectorType( float tx1, float ty1) :tx(tx1),ty(ty1){}
VectorType( ){}
};
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;
}
virtual ~Point(){}
};
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;
}
};
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 Square(s_pt,v_pt,getRadius());
}
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 s_pt.x2;
// v_pt.tx/radius();
}
float y() const
{
return s_pt.y2;
// v_pt.ty/radius();
}
};
const float EPSILON = 1e-5f;
bool is_near(float x, float y)
{
return std::abs(x - y) < EPSILON;
}
float frand()
{
return 10.0f * float(rand()) / float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0;
int max_count = 0;
float x = frand();
float y = frand();
float sx = frand();
float sy = frand();
float depth = frand();
Square square(Square::PointType(x, y), Square::VectorType(sx, sy), depth);
if (is_near(square.center().x(), x) &&
is_near(square.center().y(), y))
{
++count;
}
else
{
std::cout << " - Square::center test failed" << std::endl;
}
++max_count;
float radius = std::sqrt(sx * sx + sy * sy);
if (is_near(square.axis().x(), sx / radius) &&
is_near(square.axis().y(), sy / radius))
{
++count;
}
else
{
std::cout << " - Square::axis test failed" << std::endl;
}
++max_count;
std::cout << square.axis().x()<< " " << sx / radius<<std::endl;
std::cout << square.axis().y()<< " " << sy / radius<<std::endl;
int result = static_cast<int>(
100.0f * static_cast<float>(count) / static_cast<float>(max_count) + 0.5f
);
std::cout << "Tests passed: " << result << "%" << std::endl;
return result;
}
I'm trying to fill a vector of an object Point 3D. My app read a csv file to load the vector by the three cordinate x, y, z. I use the type float.
This is my code.
main.cpp
int main(int argc, char** argv) {
char *theFileName = "file.csv"; //[100];
vector<Point> v = getPointCloud(theFileName);
for (int i = 0; i < v.size(); ++i) {
v.at(i).print(cout);
}
}
getPointCloud
vector<Point> getPointCloud(char *fileName) {
string line;
string token;
vector<Point> v;
double tab[3];
ifstream file(fileName);
if (file.is_open()) {
while (getline(file, line)) {
int cpt = 0;
stringstream stream(line);
while (getline(stream, token, ',')) {
tab[cpt] = ::atof(token.c_str());
cpt++;
}
Point p(tab[0], tab[1], tab[2]);
p.print(cout); <-- the display works
p.setColor(255, 0, 0);
v.push_back(p);
}
file.close();
} else {
cout << "Unable to open " << fileName << '\n';
exit(0);
}
return v;
}
I have two problems:
1 - when I try to display points in the main method, I found that the three coordinates are null ( == 0) but in the displaying in the getPointCloud method works very well.
2 - Can someone give a simple method to conserve my coordinates without loss precision after mathematical operations. I have searched in the net but I don't understand haw to solve it. I'm newbie with c++.
Point.h
#ifndef POINT_H
#define POINT_H
#include <math.h>
#include <iostream>
class Point {
protected:
float x;
float y;
float z;
// color RGB
float r;
float g;
float b;
public:
// Constructors
Point();
// Point(const Point& orig);
Point(std::ostream &strm);
Point(float x, float y, float z);
Point(const Point& orig);
virtual ~Point();
//getters
float getX() const {
return this->x;
}
float getY() const {
return this->y;
}
float getZ() const {
return this->z;
}
float getR() const {
return this->r;
}
float getG() const {
return this->g;
}
float getB() const {
return this->b;
}
//setters
void setX(float x) {
this->x = x;
}
void setY(float y) {
this->y = y;
}
void setZ(float z) {
this->z = z;
}
void setR(float r) {
this->r = r;
}
void setG(float g) {
this->g = g;
}
void setB(float b) {
this->b = b;
}
void setColor(float r, float g, float b) {
this->r = r;
this->g = g;
this->b = b;
}
/**
* Print the point
* #param strm
*/
void print(std::ostream &strm);
//Other methods
float dist2D(Point &other);
float dist3D(Point &other);
Point swap(Point p);
// Point operator-(const Point &other) const;
};
#endif /* POINT_H */
Point.cpp
#include <iostream>
#include <math.h>
#include <ostream>
using namespace std;
#include "Point.h"
Point::Point(const Point& orig) {
}
Point::Point(ostream &strm) {
strm << "Type the abscissa: ", cin >> this->x;
strm << "Type the ordinate: ", cin >> this->y;
strm << "Type the applicate: ", cin >> this->z;
}
Point::Point(float x, float y, float z) : x(x), y(y), z(z) {
// The default point color is blue
this->r = 0;
this->g = 0;
this->b = 255;
}
/**
* Destructor
*/
Point::~Point() {
}
//Other methods
float Point::dist2D(Point &other) {
float xd = x - other.x;
float yd = y - other.y;
return sqrt(xd * xd + yd * yd);
}
float Point::dist3D(Point &other) {
float xd = x - other.x;
float yd = y - other.y;
float zd = z - other.z;
return sqrt(xd * xd + yd * yd + zd * zd);
}
Point Point::swap(Point p) {
Point aux(x, y, z);
x = p.x;
y = p.y;
z = p.z;
return aux;
}
//Point Point::operator-(const Point &other) const {
// return Point(other.getX() - this->x, other.getY() - this->y, other.getZ() - this->z);
//}
void Point::print(ostream &strm) {
strm << "Point(" << this->x << "," << y << "," << z << ")" << endl;
}
Thanks in advance.
Point::Point(const Point& orig) {
}
is incorrect.
It does not copy data from orig to *this
Please copy each of the member in this constructor.
This would look like this:
Point::Point(const Point& orig) {
x = orig.x ;
y = orig.y ;
x = orig.z ;
r = orig.r ;
g = orig.g ;
b = orig.b ;
}
Here is my Shape.h. Ignore all the code that is commented out. That is from a version that I believe was incorrect but I left it in there in case I was wrong.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <math.h>
#include "Point.h"
using namespace std;
class Shape {
public:
Shape() {}
virtual ~Shape() {}
/*
virtual float calcArea(const Shape& s) const = 0;
virtual float calcCircum(const Shape& s) const = 0;
virtual string calcBox(const Shape& s) const = 0;
virtual void display(const Shape& s) const = 0;
*/
virtual float calcArea() const = 0;
virtual float calcCircum() const = 0;
virtual string calcBox() const = 0;
virtual void display() const = 0;
};
class Circle : public Shape {
public:
int radius;
int pointX;
int pointY;
Point *middlePoint;
float PI;
Circle() : Shape() {
middlePoint = new Point(0,0);
radius = 0;
}
~Circle() {}
Circle(int rad, Point& p) : Shape() {
PI = 3.141592;
*middlePoint = p;
pointX = p.getX();
pointY = p.getY();
radius = rad;
}
// float calcArea(const Circle& s) const {
float calcArea() const {
float tempArea;
// tempArea = PI * s.radius * s.radius;
tempArea = PI * radius * radius;
return tempArea;
}
// float calcCircum(const Circle& s) const {
float calcCircum() const {
// int diameter = 2 * s.radius;
int diameter = 2 * radius;
float tempCircum;
tempCircum = PI * diameter;
return tempCircum;
}
// string calcBox(const Circle& s) const {
string calcBox() const {
// int x = s.pointX;
// int y = s.pointY;
// int r = s.radius;
int x = pointX;
int y = pointY;
int r = radius;
int tlX = x - r;
int tlY = y + r;
int blX = x - r;
int blY = y - r;
int trX = x + r;
int trY = y + r;
int brX = x + r;
int brY = y - r;
Point *topLeft = new Point(tlX,tlY);
Point *bottomLeft = new Point(blX,blY);
Point *topRight = new Point(trX,trY);
Point *bottomRight = new Point(brX,brY);
stringstream output;
string tempOut;
output << *topLeft << *bottomLeft << *topRight << *bottomRight;
tempOut = output.str();
return tempOut;
}
// void display(const Circle& s) const {
void display() const {
cout << "Class Name: Circle" << endl;
// float tmpArea = calcArea(s);
float tmpArea = calcArea();
cout << "Area = " << tmpArea << endl;
// cout << "Radius = " << s.radius << endl;
cout << "Radius = " << radius << endl;
// float tmpCircum = calcCircum(s);
float tmpCircum = calcCircum();
cout << "Circumference = " << tmpCircum << endl;
cout <<"Middle Point = " << middlePoint;
// string bbox = calcBox(s);
string bbox = calcBox();
cout <<"Bounding Box Points = " << bbox;
}
};
Here is my TMA4Question1.cpp code.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <math.h>
#include "Shape.h"
int main() {
Point *circlePoint = new Point(10,-5);
Circle *mainCircle = new Circle(23,*circlePoint);
}
Ok. Yes this is a homework assignment for University. I'm not looking just for the answer, I would like to know why this program gives me a segmentation fault and how to correct it.
I know the error is in the Circle code, where I pass a pointer to the circlePOint in the constructor for the Circle class. I dont know why it generates a seg fault. I hope someone can provide some insight. Thanks.
Sorry if the code is messy. Had a hard time pasting it into here properly with 4 spaces and all that.
middlePoint is not allocated in your second Circle constructor. You are assigning a value to it before giving it some memory. As an aside, I don't see why anything there needs to be a pointer.
Why do you use pointers to Points inside your classes at all? You only generate memory leaks this way and (without your own copy operations) cause problems with as the midpoints could be shared by different circles.
PS: And it's not needed to have a PI value (even as non-const) in every circle - just use the constant from (afair) cmath for it.