composition of classes in c++ - c++

This is an example of the composition of classes. But my code doesn't show a correct answer. This program must calculate the length of the line segment in the coordinates of the two ends of the line segment!
I don't know what to do in the main function. this code consists of two classes.
#include <cmath>
#include <iostream>
using namespace std;
class point {
private:
float x;
float y;
public:
void setpoint(float abscissa, float ordinate) {
x = abscissa;
y = ordinate;
}
float getx() { return x; }
float gety() { return y; }
};
class LineSegment {
public:
float length() {
result = sqrt(pow(a.getx() - b.getx(), 2) + pow(a.gety() - b.gety(), 2));
return result;
}
void displayMessage() { cout << result; }
private:
float result;
point a;
point b;
};
int main() {
point a;
float q, s;
cout << "Enter two numbers for first point:\n";
cin >> q >> s;
a.setpoint(q, s);
point b;
float e, r;
cout << "Enter two numbers for second point:\n";
cin >> e >> r;
a.getx();
a.gety();
LineSegment pt;
pt.length();
pt.displayMessage();
return 0;
}
enter image description here

The a and b local variables of your main() function are unrelated to the a and b members of class LineSegment. You should give LineSegment a constructor by which you can convey the endpoints to it, or at minimum provide a method or methods by which the endpoints can be set after the fact. You must not attempt to compute the segment length before its endpoints are set.

Neither the member a nor the member b are initialized for pt. You need to initialize them or they are initialized using the default constructor of point which happens to not do any initialization resulting in undefined behavior.
You could e.g. pass the points to the constructor of LineSegment to fix this:
class LineSegment {
public:
LineSegment(const point& p1, const point& p2)
: a(p1), b(p2)
{}
...
};
...
LineSegment pt {a, b};
...
Note: I recommend adding a prefix to member variables. m_ is one option (i.e. you'd use m_a and m_b as member variable names). This way you avoid confusion like this and also avoid shadowing of variables assuming this is the only kind of variable using this prefix.
Edit: You also never call setpoint on b in main; you need to do this before passing the points to the constructor in the above snippet.

Here is your code, touched up to work:
#include <cmath>
#include <iostream>
// using namespace std; // CHANGED: Bad practice
class point {
private:
float x = 0.0f; // CHANGED: Add default member initialization
float y = 0.0f;
public:
point() = default; // CHANGED: Add default constructor
point(int abscissa, int ordinate) : x(abscissa), y(ordinate) {} // ADDED
void setpoint(float abscissa, float ordinate) {
x = abscissa;
y = ordinate;
}
float getx() const { return x; } // CHANGED: Mark getters as const
float gety() const { return y; }
};
class LineSegment {
public:
// CHANGED: Add constructor so you can actually build a LineSegment
LineSegment(point one, point two) : a(one), b(two) {}
// CHANGED: Made a one-liner
float length() const {
return sqrt(pow(a.getx() - b.getx(), 2) + pow(a.gety() - b.gety(), 2));
}
// void displayMessage() const { std::cout << result; } // CHANGED: Not
// needed
private:
// float result; // CHANGED: Does not need to stored
point a;
point b;
};
int main() {
float q, s;
std::cout << "Enter two numbers for first point:\n";
std::cin >> q >> s;
point a(q, s); // Can now directly initialize
float e, r;
std::cout << "Enter two numbers for second point:\n";
std::cin >> e >> r;
point b(e, r); // CHANGED: Actually put values into b
// a.getx(); // CHANGED: These do nothing
// a.gety();
LineSegment pt(a, b); // CHANGED: Actually put data into pt
std::cout << "\nLine Length: " << pt.length() << '\n'; // CHANGED: Make use
// of functions now
// available
return 0;
}
Your biggest issues were not initializing your objects correctly. point b was never given the values e and r, and LineSegment pt was never given any points.
Making those small changes and your code works as expected. Just using a simple example of (0, 0) and (1, 1) provides output of 1.41421, which is root-2, which is correct.

Related

C++ Polymorphism: How to write function to accept any abstract class implementation

I want to be able to pass whatever implementation of an abstract class into a function defined in a separate file, so that I can use the functionality for other projects and write the child class however it suits me.
main.cpp:
#include "my_process.h"
struct my_guy : V2 {
my_guy(float x, float y)
: V2(x, y) { }
void double_me() override {
x *= 2.f;
y *= 2.f;
}
};
int main() {
process(my_guy(1.f,2.f));
return 0;
}
my_process.h:
#pragma once
#include <iostream>
struct V2 {
float x, y;
V2(float x, float y) {
this->x = x;
this->y = y;
}
virtual void double_me() { }
};
std::ostream& operator<<(std::ostream& output_stream, V2 vector) {
output_stream << vector.x << ", " << vector.y;
return output_stream;
}
void process(V2 vector) {
vector.double_me();
std::cout << vector << std::endl;
}
The above example prints 1,2 instead of the expected 2,4
Your function process currently passes is parameter by value.
Because you currently pass by value, a new V2 value is created as the parameter, which will always have type V2 and act like a V2.
Change it to take a reference to whatever object is passed to it:
void process(V2 & vector)
Since the parameter is also modified, you will need to pass a named variable to convince the C++ compiler that you aren't accidentally modifying a temporary.
int main() {
auto guy = my_guy(1.f,2.f);
process(guy);
}

Triangle , C++ construction, problem with calculating angles

I have a problem with my homework.
1) I should write the function SSS with inputs a, b and c. I need to output alpha, beta and gamma.
2) I should write the function SWS with inputs a, b, and gamma. And I need to output c, alpha and beta.
Here is my code:
#include <iostream>
#include <cmath>
#include <math.h>
#include <cstdio>
using namespace std;
double SSS_alpha(double a, double b, double c){
int bot1 = -2*b*c;
if(bot1==0.0){
return 0.0;
}
double alpha = acos((a*a-b*b-c*c)/bot1);
const double rad = 0.5729577951308232088;
return alpha*rad;
}
double SSS_beta(double a, double b, double c){
double bot2 = -2*c*a;
if(bot2==0.0){
return 0.0;
}
double beta = acos((b*b-c*c-a*a)/bot2);
const double rad = 0.5729577951308232088;
return beta*rad;
}
double SSS_gamma(double a, double b, double c){
double bot3 = -2*b*a;
if(bot3==0.0){
return 0.0;
}
double gamma = acos((c*c-a*a-b*b)/bot3);
const double rad = 0.5729577951308232088;
return gamma*rad;
}
double WSW_seite_c(double a, double b, double gamma){
double c_1 = (a*a+b*b-2*a*b*cos(gamma));
double c = sqrt(c_1);
return c;
}
int main(){
cout << SSS_alpha(5.0, 7.0, 8.0)<<endl;
cout <<SSS_beta(5.0, 7.0, 8.0)<<endl;
cout <<SSS_gamma(5,7,8)<<endl;
cout <<"Seite c: "<<WSW_seite_c(5, 7, 0.81)<<endl;
}
I can only return one argument in one function. And I have a lot of functions for task 1:for alpha, for beta, for gamma. And I don't know how I can write it in one function. I wrote only one function for finding c for task 2.
I am new to C++. I would be happy if you can help me.:)
Returning a struct or using a class Triangle as proposed are perfect solutions and it is what I generally use.
However, in some simple cases, returning more than one value through a tuple can be quite convenient.
I showed a simple "working" example below.
Note that I will generally avoid this kind of solution for more than 3 return objects, to avoid confusion.
#include <iostream>
#include <tuple>
std::tuple<double, double, double> f(double x, double y){
double a = x;
double b = x+y;
double c = x-y;
return std::make_tuple(a, b, c);
}
int main() {
double a, b, c;
std::tie (a, b, c) = f (1.0, 2.0);
std::cout << "a = " << a << "\n";
std::cout << "b = " << b << "\n";
std::cout << "c = " << c << "\n";
return 0;
}
I hope the code is self explaining.
The syntax can be simplified with C++17. I did not use these simplifications because my current compiler is not compatible!
This approach can be combined with the struct one, as one can return several structs through a tuple.
Edit: I just see that NathanOliver already mentioned the tuple possibility in a comment...
First you dont need cstdio if you include iostream which you should preferably do in C++ since cstdio is just the C library migrated to C++.
As for your problem it sounds like you need to pass the variables by value. Your favourite C++ Book should tell you that there are cases like yours, where you need to "return" more than one value. In that case you can pass pointers(C-Style) or the safer references to functions which kind of act like pointers.
So you actually would define your function as follows:
void SSS(double a, double b, double c, double & alpha, double & beta, double & gamma);
Or as stated by #Ripi2 pack the values in a struct and return a value of that type :
/* Thanks to NathanOliver in the comments */
struct Values {
double a;
double b;
double c;
};
Values SSS(double a, double b, double c) {
Values values;
/* Do stuff */
return values;
}
A struct will be the simplest way of doing what you want. You can also create a class, but it might be an overkill solution for a homework (they basically are the same, but see my comment thread to get my point of view on that matter).
a struct declaration goes like this :
struct containerName
{
int val_a;
double val_b;
//and so on : you put what ever you need
}
The struct then basically becomes a type you can use pretty much like int, double, bool etc.
Here's a nice reading on struct and how to use it
Yes, you can only return one object from a function. But you can have it return a compound object, like a struct or a class. Traditionally you use structs for data only objects, because that is what they were in C.
struct Triangle
{
double a;
double b;
double c;
};
Then you can return a Triangle object from a function. And access its members this way:
Triangle tri1; // first, create an instance of the struct
tri1.a = 5.0f; // assign a value to a member
It's good practice to choose meaningful names for your data types (just like with your variables) and always design the data types so that they represent what they are named.
To make the code more expressive you could take it further with a more object oriented approach. You could give the data type Triangle member functions which calculate its angles, so that you can "ask" the Triangle what its angles are.
(You should also name it a class at that point because it it is not a pure data structure anymore, but that is a matter of convention. in C++ structs and classes are almost the same.)
class Triangle
{
public:
// everything in this section can be accessed from outside
// this is a constructor. It is a special function that lets you create a Triangle
Triangle(double pa, double pb, double pc)
: a(pa), b(pb), c(pc) // initialize the members
{}
// getters for the private members (not needed but that way they can't directly be changed)
double get_a() const
{
return a;
}
double get_b() const
{
return b;
}
double get_c() const
{
return c;
}
double alpha() const;
double beta() const;
double gamma() const;
// should be const because they dont change anything about the object
private:
// the default access for classes, everything in this section can only be accessed by member functions
double a;
double b;
double c;
};
// member function definitions outside of class declaration
double Triangle::alpha() const
{
// calculate and return alpha...
}
double Triangle::beta() const
{
// calculate and return beta...
}
double Triangle::gamma() const
{
// ...
}
You can use this class this way:
int main()
{
// create a Triangle by calling the constructor
Triangle tri1(5.0, 7.0, 8.0);
std::cout << "Alpha: " << tri1.alpha() << std::endl;
std::cout << "Beta: " << tri1.beta() << std::endl;
std::cout << "Gamma: " << tri1.gamma() << std::endl;
return 0;
};

Can't assign array element to class variable while overloading "=" operator

I am quite new in C++ programming, so maybe that's why I can't figure out why this assignment is not working.
In my class, I want to overload "=" operator.
I have specified a function, that outputs variables as an array. In overloading, I want to assign those variables to new object.
obj_new = obj_with_variables
overloading:
obj_new_x=obj_with_values_parameters()[0];
obj_new_y=obj_with_values_parameters()[1];
Here is a code:
// Test1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "string"
using namespace std;
class Vector2D
{
public:
Vector2D()
{
}
Vector2D(int& a, int& b)
:x(a), y(b)
{
}
void Drukuj()
{
cout << "wektor [" << x << ',' << y << "] \n";
}
void Wspolrzedne(int&a, int&b)
{
x = a;
y = b;
}
int* Wspolrzedne()
{
int tab[2] = { x,y };
return tab;
}
void operator = (Vector2D& obj)
{
int* a = obj.Wspolrzedne();
cout << a[0] << "\n";
x = a[0];
cout << x << " what? \n";
y = a[1];
}
private:
int x, y;
};
int main()
{
int x1 = 2, x2 = 3;
Vector2D wektor(x1, x2);
wektor.Drukuj();
Vector2D wektor2;
wektor2 = wektor;
wektor2.Drukuj();
wektor.Drukuj();
return 0;
}
The problem is that it assigns some strange values. However, if I don't use a reference, but declare 2 int values (j,k) and assign array element to them [0,1], it works fine.
Also, when using static numbers (for example, instead of a[0] ; use "2") it works fine too.
What is going on?
I would be glad if somebody could point me to right answer/ resources.
Regards,
In your member function int* Wspolrzedne(), you return the address of local variable tab. Accessing this variable once its life time has ended, as you do in your = operator, is undefined behaviour.
Your code has undefined behavior because operator= is accessing invalid data. Wspolrzedne() is returning a pointer to a local variable tab that goes out of scope when Wspolrzedne() exits, thus the a pointer used in operator= is not pointing at valid data.
If you want Wspolrzedne() to return multiple values, you need to have it return (by value) an instance of a struct or class to hold them. Try something more like this:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct Coordinate {
int x;
int y;
};
class Vector2D
{
public:
Vector2D()
: x(0), y(0)
{
}
Vector2D(int a, int b)
: x(a), y(b)
{
}
Vector2D(const Coordinate &c)
: x(c.x), y(c.y)
{
}
Vector2D(const Vector2D &src)
: x(src.x), y(src.y)
{
}
void Drukuj()
{
cout << "wektor [" << x << ',' << y << "] \n";
}
void Wspolrzedne(int a, int b)
{
x = a;
y = b;
}
void Wspolrzedne(const Coordinate &c)
{
x = c.x;
y = c.y;
}
Coordinate Wspolrzedne()
{
Coordinate c = { x, y };
return c;
}
Vector2D& operator=(const Vector2D &obj)
{
Coordinate c = obj.Wspolrzedne();
cout << c.x << ',' << c.y << "\n";
Wspolrzedne(c);
return *this;
}
private:
int x;
int y;
};
On the other hand, there is no real reason to even have operator= call Wspolrzedne() to get the coordinates at all, when it can just access obj.x and obj.y directly instead:
Vector2D& operator=(const Vector2D &obj)
{
x = obj.x;
y = obj.y;
return *this;
}
In which case, you can simply eliminate your operator= altogether, and let the compiler provide a default-generated implementation that does the exact same thing for you.
Your interface is dangerous, as returning raw pointers from functions means the caller must know how to manage it. That is, the caller needs to be astutely aware of the answers to questions like, "should the caller delete the pointer or does the object I got it from retain ownership?" What is this pointer pointing to? If it's an array, now many elements are there? If I must delete it, do I use delete or delete[]?
And so on. This is not good because it's very, very error prone.
Next you have a function that returns a pointer to stack-local data. When the function returns, that memory is already invalid so the return value is always going to result in undefined behavior to read.
int* Wspolrzedne()
{
int tab[2] = { x,y };
return tab; // BAD - returns pointer to function stack data
}
Where does tab live? It's destroyed when the function exits, but you're returning a pointer to it.
This is a dangerous interface and should be changed. Perhaps you should return the values as a pair:
std::pair<int, int> Wspolrzedne()
{
return std::pair{ x,y }; // assuming c++17
// return std::pair<int, int>{x, y}; // older compilers
}
An interface like this avoids pointers, and removes all the issues mentioned above.

Nested classes error in C++

I'm self-learning C++ as a beginner, and I faced some problems regarding Nested Classes. I was trying to define a class for a quadrangle given four vertices (define a point called vertices), which
is represented by an object of a nested class for two-dimensional points. I only use one point to test my answer. My answer to the question is:
#include <iostream>
#include <assert.h>
using namespace std;
class quadrangle
{
public:
class vertex
{
private:
public:
int x, y;
friend class quadrangle;
vertex();
vertex(int a, int b);
vertex(const vertex & old);
};
vertex p1;
int a, b;
friend class vertex;
quadrangle();
quadrangle(vertex(int a, int b)) : p1(a,b) {};
quadrangle(const quadrangle & old);
void draw();
};
quadrangle::vertex::vertex()
{
x = 0; y = 0;
}
quadrangle::vertex::vertex(int a, int b)
{
x = a; y = b;
}
void quadrangle::draw()
{
cout << "p1: (" << p1.x << "," << p1.y << ") " << endl;
}
quadrangle::quadrangle()
{
p1.x = 0; p1.y = 0;
}
int main()
{
quadrangle q1(quadrangle::vertex(2,3));
q1.draw();
}
Somehow I just got
error: no matching function for call to
'quadrangle::quadrangle(quadrangle::vertex)'
and have stuck for a whole afternoon. Could someone explain what's wrong in my code?? I know something's wrong with my constructor but I just couldn't fix it...
Following is not what you expect:
quadrangle(vertex(int a, int b)) : p1(a,b) {};
it is a constructor which take a function returning vertex and taking 2 int.
and then you initialize member vertex p1 with uninitilized member a and b.
What you want is simply:
quadrangle(const vertex& v) : p1(v) {}
(And remove members a, b).
Your error tell it all, you dont have constructor:
quadrangle(const vertex & old);
and it is required to make this initialization:
quadrangle q1(quadrangle::vertex(2,3));
And this is really strange:
quadrangle(vertex(int a, int b)) : p1(a,b) { }
it looks like its a constructor taking a function prototype (or a function type?) - but its not a function pointer I guess. p1(a,b) compiles only because you have such variables in your class.
[edit]
after comment from Quentin - above declaration is a function pointer
Function types in a function parameters' declaration decay to pointers
below example shows various ways you can write function pointer as parameter to function:
std::string bar(int a, int b) {
std::cout << "bar";
return "";
}
void foo1(std::string(int a, int b)) { } // Unnamed function pointer
void foo2(std::string(pf)(int a, int b)) { pf(0,0); } // Named function pointer
void foo3(std::string(*pf)(int a, int b)) { pf(0,0);} // Named function pointer
int main() {
foo1(bar);
foo2(bar);
foo3(bar);
}

Classes - Get function - return more than one value

Let's suppose we have:
Class Foo{
int x,y;
int setFoo();
}
int Foo::setFoo(){
return x,y;
}
All I want to achieve is form my get function to return more than one value. How can I do this?
C++ doesn't support multiple return values.
You can return via parameters or create an auxiliary structure:
class Foo{
int x,y;
void setFoo(int& retX, int& retY);
};
void Foo::setFoo(int& retX, int& retY){
retX = x;
retY = y;
}
or
struct MyPair
{
int x;
int y;
};
class Foo{
int x,y;
MyPair setFoo();
};
MyPair Foo::setFoo(){
MyPair ret;
ret.x = x;
ret.y = y;
return ret;
}
Also, shouldn't your method be called getFoo? Just sayin...
EDIT:
What you probably want:
class Foo{
int x,y;
int getX() { return x; }
int getY() { return y; }
};
You can have reference parameters.
void Foo::setFoo(int &x, int &y){
x = 1; y =27 ;
}
You can't return more than one object per se, but what you can do is use either std::pair from <utility> or std::tuple from <tuple> (the latter only available in the latest C++ standard) to pack more than one value together and return them as one object.
#include <utility>
#include <iostream>
class Foo
{
public:
std::pair<int, int> get() const {
return std::make_pair(x, y);
}
private:
int x, y;
};
int main()
{
Foo foo;
std::pair<int, int> values = foo.get();
std::cout << "x = " << values.first << std::endl;
std::cout << "y = " << values.second << std::endl;
return 0;
}
You cannot really return multiple values in c++. But you can modify multiple values by reference
C++ does not allow you to return multiple values. You can return a type that contains multiple values. But you can only return one type from a C++ function.
For example:
struct Point { int x; int y; };
Class Foo{
Point pt;
Point setFoo();
};
Point Foo::setFoo(){
return pt;
}
You can use std::pair for two returned variables and std::tuple (C++11 only) for more of them.
You can not return more than 1 variable.
But you can do pass by reference, and modify that variable(s).
// And you pass them by reference
// What you do in the function, the changes will be stored
// When the function return, your x and y will be updated with w/e you do.
void myFuncition(int &x, int &y)
{
// Make changes to x and y.
x = 30;
y = 50;
}
// So make some variable, they can be anything (including class objects)
int x, y;
myFuncition(x, y);
// Now your x and y is 30, and 50 respectively when the function return
cout << x << " " << y << endl;
Edit: To answer your question on how to get: Instead of returning just 1 variable, you pass some variables, so your function can modify them, (and when they return), you will get them.
// My gen function, it will "return x, y and z. You use it by giving it 3
// variable and you modify them, and you will "get" your values.
void myGetFunction(int &x, int &y, int &z)
{
x = 20;
y = 30;
z = 40;
}
int a, b, c;
// You will "get" your 3 value at the same time when they return.
myGetFunction(a, b, c);