Accessing Class Member Variables with [] operator - c++

I'm going through a book and I saw something interesting that I don't quite understand how it works.
What is happening under the hood of C++? Are the member variables laid out in an array like fashion. Does it only work for member variables of the same type?
I added a string type as the fourth variable just to see what happens and the output for [3] is 1.75518e-317.
Vector3D b{1, 2, 3, "56"};
cout << b[3] << "\n";
Here is the code:
vector.h
public Vector3D {
public:
double x;
double y;
double z;
Vector3D(double a = 0.0, double b = 0.0, double c = 0.0)
{
x = a;
y = b;
z = c;
}
double &operator[](int i)
{
return ((&x)[i]);
}
}
main.cpp
int main(int argc, char const *argv[])
{
Vector3D a{1, 2, 3};
Vector3D b{1, 2, 3};
cout << b[0] << "\n";
cout << b[1] << "\n";
cout << b[2] << "\n";
return 0;
}
Output:
1
2
3
Note: This code is a learning exercise only and I am not using it for anything.

Related

Why does the second variable not change in the field?

I'm testing some programms for my lectures. I'm creating classes and use a paramterlist to initalize a field but the second variable doesn't change.
#include <iostream>
using namespace std;
class Punkt {
int x;
int y;
public:
Punkt(int a = 0, int b = 0)
{
x = a;
y = b;
}
void printXY()
{
cout << "x= " << x << " y= " << y << endl;
}
};
int main() {
Punkt pFeld[] = { (1, 1), (2, 2), (3, 3) };
for (int i = 0; i < 3; i++)
pFeld[i].printXY();
cin.get();
};
No error messages. Expected result was that x and y change, while actual result is that only x changes and y stays 0.
This
(1, 1)
is an expression with the comma operator.
In fact this initialization
Punkt pFeld[] = { (1, 1), (2, 2), (3, 3) };
is equivalent to
Punkt pFeld[] = { 1, 2, 3 };
So the constructor with the second default argument equal to 0 is called three times.
Use instead
{ 1, 1 }
Here is your updated code
#include <iostream>
using namespace std;
class Punkt {
int x;
int y;
public:
Punkt(int a = 0, int b = 0)
{
x = a;
y = b;
}
void printXY()
{
cout << "x= " << x << " y= " << y << endl;
}
};
int main() {
Punkt pFeld[] = { {1, 1}, {2, 2}, {3, 3} };
for (int i = 0; i < 3; i++)
pFeld[i].printXY();
cin.get();
}
Its output is
x= 1 y= 1
x= 2 y= 2
x= 3 y= 3
Pay attention to that the semicolon after the function main is redundant.
Passing (1, 1) to the constructor of Punkt, the comma operator will return the 2nd operand as the result (the 1st operand is discarded), so you're only passing one int with value 1 to the constructor. That's why y is always initialized as 0.
What you want should be
Punkt pFeld[] = { {1, 1}, {2, 2}, {3, 3} }; // list initialization since C++11
or
Punkt pFeld[] = { Punkt(1, 1), Punkt(2, 2), Punkt(3, 3) };

How to round float to up and down value c++ with own function?

double round(double a)
{
double b, c, f, g;
float d[2];
c = modf(a, &b);
if (a > 0) {
f = a - c;
g = a - c + 1;
d[0] = f;
d[1] = g;
return d[0], d[1];
}
else {
f = a - c;
g = a - c - 1;
d[0] = f;
d[1] = g;
return d[0], d[1];
}
}
I need to get 2 numbers it the end(for ex: if I have num 12.34, I want to get 12 and 13)This is my function of rounding for pos and neg numbers. But it returns only 1 value(( So I'm stack...pls, help how to return 2 values?
You cannot return two things in the return, so return d[0],d[1] compiles but doesn't work as you expect. You can use two reference parameters in the function prototype to return. Something like void round(double a, double* result1, double* result2). Into the function, set d[0] to *result1 and d[1] to *result2.
Another thing: Are you sure the line g = a - c - 1; when a is negative is correct? I think you need to do g = a + c - 1;, because a is negative.
#include "pch.h"
#include <iostream>
#include <array>
using namespace std;
auto rounding(double x)
{
int part = static_cast<int>(x);
if (x < 0.0)
{
return array<int, 2> {
part - 1, part
};
}
else
{
return array<int, 2> {
part, part + 1
};
}
}
int main()
{
double x;
cout << "Please, enter a float number to round: ";
cin >> x;
auto r1 = rounding(x);
if (x > 0) {
cout << "A lower value: " << r1[0] << endl << "A bigger value: " << r1[1];
}
else {
cout << "A bigger value: " << r1[0] << endl << "A lower value: " << r1[1];
}
}

working of constructor c++

Help me figure out how the line p1(10,15); works and From where p1 derive from as it was never declared.
I am learning how constructor works
i used this link link
#include<iostream>
using namespace std;
class Point
{
private:
int x, y;
public:
// Parameterized Constructor
Point(int x1, int y1)
{
x = x1;
y = y1;
}
int getX()
{
return x;
}
int getY()
{
return y;
}
};
int main()
{
// Constructor called
Point p1(10, 15);
// Access values assigned by constructor
cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
return 0;
}
When you make an instance of class Point, it automatically call constructor and do the assignment.
Point p1(10, 15);
it's like this:
Point(10, 15)
{
x = 10;
y = 15;
}
and you using 2 functions to get x,y :
cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();

Optional logic when passing structures in c++

I am new too programming and am trying to pass an array of structures and an "option" to a function. I then want the function to be able to manipulate the data within the the array of the struct.
struct coordinates{
int x;
int y;
int z;
}COORD;
The option parameter is an integer that will specify which part of the structure to manipulate.
Manipulate x --- option = 0
Manipulate y --- option = 1
Manipulate z --- option = 2
An example of this is shown below. The function takes the array of structs and makes a 3 point moving average of the data-point specified data point. The issue I am having is that the program I am trying to build has 50+ members in each struct so writing out each if statement by hand is really tedious. What I am asking is if there is a more elegant solution???
#include <iostream>
struct coordinates{
int x;
int y;
int z;
}COORD;
int main() {
COORD points[10];
// Initialising points
for(int i = 0, i < 10, i++){
points[i].x = 1;
points[i].y = 2;
points[i].z = 3;
}
//(struct,startpoint,option)
std::cout << movingaverage(&points,3,1); // Output
}
int movingaverage(COORD *data, int start_point, int option){
if(option == 0) {
// Assigns the "start" value of the sum value.
sum = data[start_point]->x;
sum = sum + data[start_point - 1]->x;
sum = sum + data[start_point + 1]->x;
}
else if(option == 1) {
// Assigns the "start" value of the sum value.
sum = data[start_point]->y;
sum = sum + data[start_point - 1]->y;
sum = sum + data[start_point + 1]->y;
}
else if(option == 2) {
// Assigns the "start" value of the sum value.
sum = data[start_point]->z;
sum = sum + data[start_point - 1]->z;
sum = sum + data[start_point + 1]->z;
}
sum = sum / n;
return sum; //Sum is the moving average
}
Also pointer to members are a possible solution; in combination with a template function, the members can be of different type. But, yes, the syntax is something strange:
#include <iostream>
#include <vector>
using namespace std;
/// calculate the sum of a given structure member in a vector:
template <typename T, typename M>
M membersum(vector<T> array, M (T::*mptr)) {
M sum = 0;
for (int i=0; i<array.size(); i++) {
sum += (array[i].*mptr);
}
return sum;
}
struct Point {
Point(int x, int y, float z): x(x), y(y), z(z) {}
int x;
int y;
float z;
};
int main() {
vector<Point> points;
points.push_back(Point(1,2,3.8));
points.push_back(Point(1,2,4.5));
points.push_back(Point(1,2,1.7));
// your code goes here
cout << "sum x: " << membersum(points, &Point::x) << endl;
cout << "sum y: " << membersum(points, &Point::y) << endl;
cout << "sum z: " << membersum(points, &Point::z) << endl;
return 0;
}
This example I created on ideone.com.
C++ does not support reflection and therefore you cannot iterate over members of a struct. The way I would do this is with a getter function.
template<class Getter>
int movingaverage(COORD *data, int start_point, const Getter &get){
auto sum = get(data[start_point]);
sum = sum + get(data[start_point - 1]);
sum = sum + get(data[start_point + 1]);
return sum;
}
std::cout << "x: " << movingaverage(&points, 3, [](const COORD &coord){return coord.x;}) << '\n';
std::cout << "y: " << movingaverage(&points, 3, [](const COORD &coord){return coord.y;}) << '\n';
std::cout << "z: " << movingaverage(&points, 3, [](const COORD &coord){return coord.z;}) << '\n';
If you or your compiler are confused about the lambda part you can just write a regular function and pass that instead.
I would suggest to use a simple functor.
Class MovingAvg
{
MovingAvg(std::vector<Coordinate> *pSet);
void SetPointSet(std::vector<Coordinate> *p);
double operator()(int startPoint, int option)
{
//calculation here.
double sum = 0;
for(int i = -1; i <= 1; ++i)
{
switch(option)
case 0:
sum += pointSet[startPoint + i].x; //check for bounday conditions.
.................
}
return sum / 3;
}
private:
//container
std::vector<Coordinate> *pointSet;
}
Use it as.
MovAvg mvG(pointSet);
double sum = mvG(startP, option);
//change the private member if the point set must be changed.
Functors are pretty handy in cases like this.
You can try something along the lines of
class coordinates{
private:
int xyz[3]; //implementation detail(!)
public:
int x() const { return xyz[0]; }
int y() const { return xyz[1]; }
int z() const { return xyz[2]; }
//some relevant setters go here
static int movingaverage(COORD *data, int start_point, int option){
sum = data[start_point]->xyz[option];
sum = sum + data[start_point - 1]->xyz[option];
sum = sum + data[start_point + 1]->xyz[option];
}
};

C++ segment line intersection

i would like to ask where is the problem?
I got an error: invalid type argument of ‘unary *’
I am new in c++ programming, i use java style.
Pointer and dereference is a big problem for me.
My application got input values and save as point object, after this i should find intersection of 2 lines.
I thought to return a Point object in which i will compute x and y value.
.h file
class Point {
public:
double x_val, y_val;
Point(double, double);
double x();
double y();
double dist(Point other);
Point add(Point b);
Point sub(Point b);
void move(double a, double b);
};
class Triungle {
public:
Triungle(std::string);
void compute_length();
void lines_intersect(Point a, Point b, Point c, Point d, Point *intersection);
Point a, b, c;
};
.cpp file
Point::Point(double x = 0.0, double y = 0.0) {
x_val = x;
y_val = y;
}
double Point::x() {
return x_val;
}
double Point::y() {
return y_val;
}
double Point::dist(Point other) {
double xd = this->x() - other.x();
double yd = this->y() - other.y();
return sqrt(xd * xd + yd * yd);
}
Point Point::add(Point b) {
return Point(x_val + b.x_val, y_val + b.y_val);
}
Point Point::sub(Point b) {
return Point(x_val - b.x_val, y_val - b.y_val);
}
void Point::move(double a, double b) {
x_val += a;
y_val += b;
}
void Triungle::lines_intersect(Point a, Point b, Point c, Point d, Point *intersection) {
double x, y;
double A1 = b.y_val - a.y_val;
double B1 = b.x_val - a.x_val;
double C1 = a.y_val - (A1 / B1) * a.x_val;
double A2 = d.y_val - c.y_val;
double B2 = d.x_val - c.x_val;
double C2 = c.y_val - (A2 / B2) * c.x_val;
double det = (A1 / B1) - (A2 / B2);
if (det == 0) {
// lines are paralel
} else {
x = (C2 - C1) / det;
y = (A1 * C2 - A2 * C1) / det;
}
*intersection->x_val = x; // here i got error
*intersection->y_val = y; // here i got error
}
Triungle::Triungle(std::string s) {
cout << "enter first point of " << s << " triangle: ";
cin >> a.x_val;
cin >> a.y_val;
if (!(cin)) {
cout << "input error." << endl;
exit(1);
}
cin.clear();
cout << "enter second point of " << s << " triangle: ";
cin >> b.x_val;
cin >> b.y_val;
if (!(cin)) {
cout << "input error." << endl;
exit(1);
}
cin.clear();
cout << "enter 3 point of " << s << " triangle: ";
cin >> c.x_val;
cin >> c.y_val;
if (!cin) {
cout << "input error." << endl;
exit(1);
}
cin.clear();
}
and i call function in this way
int main(int argc, char** argv) {
Triungle a("first");
Triungle b("second");
Point p;
a.lines_intersect(a.a, a.b, a.c, a.a, &p);
}
intersection->member
will dereference a pointer intersection. This is the same as
(*intersection).member
you don't need to dereference it twice.
What you do in your code
*intersection->x_val = x;
is an equivalent to
(*(intersection->x_val)) = x;
because operator of selection through pointer -> has higher precedence than dereference operator *, and the latter has higher precedence than assignment operator =.
So first your select member double x_val of class Point.
Second you try to apply unary dereference operator * to the result. And because x_val is double, not a pointer, which is expected by dereference operator, compiler reports an error.
Thus, dereference operator is excessive here and it's enough to do the following
intersection->x_val = x;
Assuming that the error you get is a compilation error on the two lines:
*intersection->x_val = x; // here i got error
*intersection->y_val = y; // here i got error
The problem is that you are de-referencing a pointer, and then using the derefencing operator -> on it.
Instead, you should either do:
intersection->x_val = x;
intersection->y_val = y; // leave it as a pointer
or
*intersection.x_val = x;
*intersection.y_val = y; // use it as an object