I am trying to understand the concept of copy constructor. With copy constructor I get desired result. But with out copy constructor I get the same result. The code is given here:
#include<iostream>
using namespace std;
class Point
{
private:
int x, y;
public:
Point(int x1, int y1) { x = x1; y = y1; }
// Copy constructor
// Point(const Point &p2) {x = p2.x; y = p2.y; }
void set()
{
x=50;
y = 100;
}
int getX() { return x; }
int getY() { return y; }
};
int main()
{
Point p1(10, 15); // Normal constructor is called here
Point p2 = p1 ;
// p2 = p1;
cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();
p2.set();
cout << "\np1.x = " << p1.getX() << ", p1.y = " << p1.getY();
cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();
// Copy constructor is called here
// Let us access values assigned by constructors
return 0;
}
The out put is :
p1.x = 10, p1.y = 15
p2.x = 10, p2.y = 15
p1.x = 10, p1.y = 15
p2.x = 50, p2.y = 100
Shouldn't it be :
p1.x = 10, p1.y = 15
p2.x = 10, p2.y = 15
p1.x = 50, p1.y = 100
p2.x = 50, p2.y = 100
Edit 1 : What if I initialize objects like this:
Point p1(10, 15); // Normal constructor is called here
Point p2(11,10);
p2 = p1;
Will it call copy constructor? If not, why in this case the result is the same?
C++ makes a distinction between objects and references to objects. If you want
p2 and p1 to point to the same Point, you should do this:
Point& p2 = p1;
Because you never defined a copy constructor for your Point class, the compiler gave you one. It will effectively look like this:
Point(const Point& other) : x(other.x), y(other.y)
{}
And your code, Point p2 = p1 will call this copy constructor.
This causes the integer values to be copied, not point to the same location in memory.
But without copy constructor I get the same result.
This is because you get a default copy constructor and a default assignment operator inserted for you by the compiler. It does precisely the same thing as your hand-written copy constructor does, so there is no need to code one manually.
Shouldn't it [the optput] be ...
No, it should not. In your code p1 and p2 are different unrelated objects, even though the initial state of p2 comes from p1.
You need to use pointers or references to get the behavior that you want:
// Point p2 = p1;
Point& p2(p1);
Now p2 behaves as an "alias" for p1, so there is really one object.
demo
A copy constructor is called usually in cases of declaration and initialization of object to another object at same time, or while passing to functions. What the first statement means is:
Point p1(10,15);
Point p2(p1);
Is an example of usage of copy constructor while,
Point p1(10,15);
Point p2;
p2=p1;
is just plain assignment.
And No. Your output is right in the first case. A copy constructor just copies the values of one object into another, it doesn't make the new one a reference object.
Also, the main use of copy constructor is usually in functions.
As a footnote, to understand constructors and when they are called, you could use different cout statements in them. Then you'll know when a particular constructor is called.
P.S. I'm a beginner, so please tell me if I've got anything wrong.
Related
In c++ you can swap 2 numbers without 3rd variable:
int x = 10;
int y = 5;
x ^= y;
y ^= x;
x ^= y; //x = 5, y = 10
So I wonder if there is a similar way to swap 2 structs without 3rd variable:
struct Position{int x, y;};
int main()
{
Position firstPose{x = 10, y = 5;};
Position secPose{x = 5, y = 10;};
//Now I want to swap firstPose with secPose.
}
Is this possible? if so; how to do it
There is no a standard way to swap two structure without an intermediate copy. Arguably, one of the main benefit of swap "is" the intermediate copy, this wonderful article explain how swap is a crucial part to achieve "strong exception guarantee". https://www.stroustrup.com/except.pdf
Furthermore, if the goal is to not make a copy of the struct (because is resource intensive) you can design your class using the pimpl idiom and swap just the pointer (you will still have a third variable but it will be just the raw pointer to the structure).
If you want to use C++ effectively make yourself familiar with exception safety, it is truly of of the area where the language gives its best
A bit old but still good article: http://www.gotw.ca/gotw/008.htm
At the end, the final solution is create a custom swap function:
#include <iostream>
#include <string>
struct Position{int x, y;};
void swap(Position& a, Position& b)
{
a.x ^= b.x;
b.x ^= a.x;
a.x ^= b.x;
a.y ^= b.y;
b.y ^= a.y;
a.y ^= b.y;
}
int main()
{
Position a = { 10, 100};
Position b = { 20, 200};
swap(a, b);
std::cout << "a:" << a.x << "," << a.y << std::endl;
std::cout << "b:" << b.x << "," << b.y << std::endl;
}
IMHO, the last option is more for personal amusement than real production code.
Yes, there are some ways to achieve your requirement. But, note that the XOR method of swapping between two values is quite inefficient.
First of all, let's assume the required struct:
struct position {
int x;
int y;
};
Method 1
Create your own swap() function:
void swap(position &pos1, position &pos2) {
// Swapping X
verify_overflow(pos1.x, pos2.x); // See about this below
pos1.x = pos1.x + pos2.x;
pos2.x = pos1.x - pos2.x;
pos1.x = pos1.x - pos2.x;
// Swapping Y
verify_overflow(pos1.y, pos2.y); // See about this below
pos1.y = pos1.y + pos2.y;
pos2.y = pos1.y - pos2.y;
pos1.y = pos1.y - pos2.y;
}
Now, you can implement it like this:
swap(v1, v2);
Note: To prevent undefined-behavior due to the overflows, the following subroutine could be used:
inline void verify_overflow(signed int si_a, signed int si_b) {
signed int sum;
if (__builtin_sadd_overflow(si_a, si_b, &sum)) {
std::cerr << "[error] Overflow is possible to happen.\n";
exit(1);
}
}
For example, when you set a struct:
position v1 = {2147483647, 2147483644};
The program will yield the following error, then UB won't occur:
[error] Overflow is possible to happen.
Method 2
There is already a built-in std::swap() in C++ standard. Its benefit is that you won't need to keep changing the code when the struct alters. The code should look like this:
#include <iostream>
struct position {
int x;
int y;
};
int main(void) {
position v1 = {5, 10};
position v2 = {10, 5};
std::swap(v1, v2);
std::cout << v1.x << ' ' << v1.y << std::endl;
std::cout << v2.x << ' ' << v2.y << std::endl;
return 0;
}
This question already has answers here:
Order of calling base class constructor from derived class initialization list
(3 answers)
Are parent class constructors called before initializing variables?
(7 answers)
Closed 2 years ago.
In my code, there are two classes:
Vect3 which represents a vector in 3D i.e. x, y & z
Plane which represents the coefficients in the equation of plane i.e. a, b, c, & d
Now, Vect3 is my base class and Plane is the derived one.
Vect3 class (base class):
class Vect3 {
public:
Vect3(float x, float y, float z);
Vect3(std::vector<float> vec);
void printVect3() const;
void printVect3Magnitude() const;
void printAngleWrtAxisDeg();
float rad2deg(float angle_in_rad);
protected:
float _x = 0.0;
float _y = 0.0;
float _z = 0.0;
float _magnitude = 0.0;
float _angle_wrt_X = 0.0;
float _angle_wrt_Y = 0.0;
float _angle_wrt_Z = 0.0;
void _doCalculation();
};
Vect3::Vect3(float x, float y, float z) : _x(x), _y(y), _z(z) {
_doCalculation();
}
Vect3::Vect3(std::vector<float> vec) : _x(vec[0]), _y(vec[1]), _z(vec[2]) {
_doCalculation();
}
void Vect3::_doCalculation() {
_magnitude = sqrt(_x * _x + _y * _y + _z * _z);
_angle_wrt_X = acos(_x / _magnitude);
_angle_wrt_Y = acos(_y / _magnitude);
_angle_wrt_Z = acos(_z / _magnitude);
}
void Vect3::printVect3() const {
std::cout << "x = " << _x << " | y = " << _y << " | z = " << _z << "\n";
}
void Vect3::printVect3Magnitude() const {
std::cout << _magnitude << "\n";
}
void Vect3::printAngleWrtAxisDeg() {
std::cout << "Angle in degree, "
<< "wrt X-axis = " << rad2deg(_angle_wrt_X)
<< " | wrt Y-axis = " << rad2deg(_angle_wrt_Y)
<< " | wrt Z-axis = " << rad2deg(_angle_wrt_Z) << "\n";
}
float Vect3::rad2deg(float angle_in_rad) {
return (angle_in_rad * 180.0 / M_PI);
}
Plane class (derived class):
class Plane : public Vect3 {
public:
Plane(std::vector<float> plane_coefficients);
private:
float _a = 0.0;
float _b = 0.0;
float _c = 0.0;
float _d = 0.0;
};
Plane::Plane(std::vector<float> plane_coefficients) : _a(plane_coefficients[0]), _b(plane_coefficients[1]), _c(plane_coefficients[2]), _d(plane_coefficients[3]), Vect3(_a, _b, _c) {
std::cout << "from Plane class: " << _x << " " << _y << " " << _z << "\n";
}
However, for the following main,
int main() {
std::vector<float> vec1 = {1.0, 1.0, 1.0, 1.0};
Plane plane1(vec1);
plane1.printVect3Magnitude();
plane1.printAngleWrtAxisDeg();
std::cout << "= = = = = = = = = = = =\n";
Vect3 vect3d(vec1);
vect3d.printVect3Magnitude();
vect3d.printAngleWrtAxisDeg();
return 0;
}
I'm getting somewhat weird output:
from Plane class: 3.07795e-41 2.8026e-45 0
0
Angle in degree, wrt X-axis = nan | wrt Y-axis = nan | wrt Z-axis = -nan
= = = = = = = = = = = =
1.73205
Angle in degree, wrt X-axis = 54.7356 | wrt Y-axis = 54.7356 | wrt Z-axis = 54.7356
In the plane constructor, using initializer list, I'm already updating _a, _b, & _c first and then passing them to Vect3 constructor.
So, ideally, output of printVect3Magnitude() & printAngleWrtAxisDeg() method of object plane and object vect3d should be same.
However, based on the above output, it looks like garbage values are being passed to Vect3 constructor!!
On the other hand, if I modify plane constructor as follow (i.e. rather than passing _a, _b, _c to Vect3 constructor, directly pass input vector plane_coefficients)
Plane::Plane(std::vector<float> plane_coefficients) : _a(plane_coefficients[0]), _b(plane_coefficients[1]), _c(plane_coefficients[2]), _d(plane_coefficients[3]), Vect3(plane_coefficients) {
std::cout << "from Plane class: " << _x << " " << _y << " " << _z << "\n";
}
then I'm getting the expected output:
from Plane class: 1 1 1
1.73205
Angle in degree, wrt X-axis = 54.7356 | wrt Y-axis = 54.7356 | wrt Z-axis = 54.7356
= = = = = = = = = = = =
1.73205
Angle in degree, wrt X-axis = 54.7356 | wrt Y-axis = 54.7356 | wrt Z-axis = 54.7356
But why? Am I mistaken regarding the order in which the class members are being updated and passed to the base class constructor (before it gets called) in the initializer list?
Did you notice the compiler warnings?
Regardless of how you order the members and base classes in the constructor initializer list, they will be constructed in the declaration order and destructed in the reverse declaration order. Since base list is declared before the block that nests all members, all base sub-objects precede members while construction. If - in the constructor initializer list - the initializer for members and/or bases is miss-placed, a diagnostic warning is generated, but the code compiles . And if a member or base is initialized to the value of another base/member declared after itself, UB will result - as the OP has already observed.
Best,
FM.
Related questions:
Why this move constructor is not called wtih rvalue temporary? [duplicate]
Move Constructor vs Copy Elision. Which one gets called?
move Constructor is not called
I'm posting this question because this thing of the move semantics is really puzzling me. At first they seemed quite clear to me, but when I tried to demostrate the use of those to myself, then I realized that maybe I've misunderstood something.
I've tried to arrange the following file to be a not-so-trivial implementation of a vector-like class making use of move semantics (actually the main function is there as well, together with a free function to make printing to screen easier, ...). It is not really a minimal working example, but the output it produces to screen is reasonably readable, imho.
Still, if you thing it's better to slim it down, please suggest me what to do.
Anyway the code is the following,
#include<iostream>
using namespace std;
int counter = 0; // to keep count of the created objects
class X {
private:
int id = 0; // hopefully unique identifyier
int n = 0;
int * p;
public:
// special member functions (ctor, dtor, ...)
X() : id(counter++), n(0), p(NULL) { cout << "default ctor (id " << id << ")\n"; }
X(int n) : id(counter++), n(n), p(new int[n]) { cout << "param ctor (id " << id << ")\n"; };
X(const X& x) : id(counter++), n(x.n), p(new int[n]) {
cout << "copy ctor (id " << id << ") (allocating and copying " << n << " ints)\n";
for (int i = 0; i < n; ++i) {
p[i] = x.p[i];
}
};
X(X&& x) : id(counter++), n(x.n), p(x.p) {
cout << "move ctor (id " << id << ")\n";
x.p = NULL;
x.n = 0;
};
X& operator=(const X& x) {
cout << "copy assignment (";
if (n < x.size() && n > 0) {
cout << "deleting, ";
delete [] p;
n = 0;
}
if (n == 0) {
cout << "allocating, and ";
p = new int[n];
}
n = x.size();
cout << "copying " << n << " values)";
for (int i = 0; i < n; ++i) {
p[i] = x.p[i];
}
cout << endl;
return *this;
};
X& operator=(X&& x) {
this->n = x.n;
this->p = x.p;
x.p = NULL;
x.n = 0;
cout << "move assignment (\"moving\" " << this->n << " values)\n";
return *this;
};
~X() {
cout << "dtor on id " << id << " (array of size " << n << ": " << *this << ")\n";
delete [] p;
n = 0;
}
// getters/setters
int size() const { return n; }
// operators
int& operator[](int i) const { return p[i]; };
X operator+(const X& x2) const {
cout << "operator+\n";
int n = min(x2.size(), this->size());
X t(n);
for (int i = 0; i < n; ++i) {
t.p[i] = this->p[i] + x2.p[i];
}
return t;
};
// friend function to slim down the cout lines
friend ostream& operator<<(ostream&, const X&);
};
int main() {
X x0;
X x1(5);
X x2(5);
x1[2] = 3;
x2[3] = 4;
cout << "\nx0 = x1 + x2;\n";
x0 = x1 + x2;
cout << "\nX x4(x1 + x2);\n";
X x4(x1 + x2);
cout << x4 << endl;
cout << '\n';
}
// function to slim down the cout lines
ostream& operator<<(ostream& os, const X& x) {
os << '[';
for (int i = 0; i < x.size() - 1; ++i) {
os << x.p[i] << ',';
}
if (x.size() > 0) {
os << x.p[x.size() - 1];
}
return os << ']';
}
When I compile and run it with
$ clear && g++ moves.cpp && ./a.out
the output is the following (#-comments are added by hand)
default ctor (id 0)
param ctor (id 1)
param ctor (id 2)
x0 = x1 + x2;
operator+
param ctor (id 3)
move assignment ("moving" 5 values)
dtor on id 3 (array of size 0: [])
X x4(x1 + x2);
operator+
param ctor (id 4)
[0,0,3,4,0]
dtor on id 4 (array of size 5: [0,0,3,4,0])
dtor on id 2 (array of size 5: [0,0,0,4,0])
dtor on id 1 (array of size 5: [0,0,3,0,0])
dtor on id 0 (array of size 5: [0,0,3,4,0])
From the first part of the output, I guess that I really demonstrated the intended use of the move assignment operator. Am I right, in this respect? (From the next output, it seems I'm not, but I'm not sure.)
At this point, if my deduction that copy elision prevented the call to the copy ctor is right, then one question comes natural to me (and not only me, see OP's comment here):
Isn't that situation of creating an object based on another temporary object (e.g. x4 based on the result of x1 + x2 in X x4(x1 + x2);) exactly the one for which move semantics where supposed to be introduced? If not, what is a basic example to show the use of the move ctor?
Then I read that copy elision can be prevented by adding a proper option.
The output of
clear && g++ -fno-elide-constructors moves.cpp && ./a.out
however, is the following:
default ctor (id 0)
param ctor (id 1)
param ctor (id 2)
x0 = x1 + x2;
operator+
param ctor (id 3)
move ctor (id 4)
dtor on id 3 (array of size 0: [])
move assignment ("moving" 5 values)
dtor on id 4 (array of size 0: [])
X x4(x1 + x2);
operator+
param ctor (id 5)
move ctor (id 6)
dtor on id 5 (array of size 0: [])
move ctor (id 7)
dtor on id 6 (array of size 0: [])
[0,0,3,4,0]
dtor on id 7 (array of size 5: [0,0,3,4,0])
dtor on id 2 (array of size 5: [0,0,0,4,0])
dtor on id 1 (array of size 5: [0,0,3,0,0])
dtor on id 0 (array of size 5: [0,0,3,4,0])
+enrico:CSGuild$
where it looks like the call to the move ctor I expect is now there, but both that call and the call to the move assignment are preceded by another call to the move ctor each.
Why is this the case? Have I completely misunderstood the meaning of move semantics?
You appear to have two questions here:
why is the move constructor not called for X x4(x1 + x2)?
why, when copy elision is disabled, is the move constructor called twice?
The first question
Isn't that situation (X x4(x1 + x2);) exactly the one for which move
semantics where supposed to be introduced?
Well, no. In order to use move semantics you're effectively suggesting that we should choose to construct an X in operator+, and then move it to the result x4, which is clearly inefficient compared to a copy-elided construct the final result (x4) in place during operator+.
The second question
Having disabled copy-elision, why do we see two calls to the move constructor during X x4(x1 + x2)? Consider that there are three scopes in play here:
the operator+ scope, where we construct an X and return it;
the main scope where we are calling X x4(x1 + x2);
the X constructor where we are constructing an X from x1 + x2;
Then, in the absence of elision, the compiler is:
moving the result from operator+ to main (into x1 + x2); and
moving the content of x1 + x2 into x4.
For one of our class assignments we had to implement a polynomial class. It stores the coefficients of a polynomial and outputs the answer.
In my class definition, I have a friend operator that outputs the function:
friend std::ostream& operator << (std::ostream& out, Polynomial& p);
and my implementation is as follows:
std::ostream& operator << (std::ostream& out, Polynomial& p) {
double ans = 0;
for(int i = 0; i <= p.order; ++i)
ans += (double)p.coefficents[i] * pow(p.x, i);
out << ans;
return out;
}
My main function (written by my instructor) is:
int main ()
{
Polynomial p1 (0.5,3); // Invokes two argument constructor for p1
p1.inputCoefficients(); // Set the coefficient of polynomial p1
cout << "Polynomial p1 evaluates to " << p1 << endl;
Polynomial p2(p1), p3; // Copy constructor for p2 and default constructor for p3
cout << "Polynomial p2 evaluates to " << p2 << endl;
cout << "Polynomial p3 evaluates to " << p3 << endl;
p3 = p2; // Copy assignment operator
return 0;
}
My question is:
When I run my program with this line of code:
double ans = 0;
my output is this:
Polynomial p1 evaluates to 1.375
Polynomial p2 evaluates to 1.375
Polynomial p3 evaluates to 0
Polynomial destroyed!
Polynomial destroyed!
Polynomial destroyed!
Which is the correct output
but if I change that line to this:
double ans;
Unexpected things start to happen:
Polynomial p1 evaluates to 1.375
Polynomial p2 evaluates to 1.375
Polynomial p3 evaluates to 1.375
Polynomial destroyed!
Polynomial destroyed!
Polynomial destroyed!
Why is p3 evaluated to 1.375? p3 was created using the default constructor so wouldn't it output 0?
As soon as the polynomial is outputted wouldn't the scope of ans die? Even if it didn't, or ans kept the value from the last time it ran, then wouldn't p2 be doubled (be 2.75) because the << operator ran twice?
Please feel free to get technical and offer advice, I'm curious and want to know the insides of what's actually going on.
Here is the entirety of my code (for reference):
/*
Using dynamic arrays, implement a polynomial class. In mathematics, polynomial is a function of the form f(x) = a0*x^0 + a1*x^1 + a2*x^2 + a3*x^3 + ....n terms. Here, a0, a1, a2 etc. are the coefficients of the polynomial and n is the order of the polynomial.
The private variables include the value of x (a real number), the order of the polynomial (an integer) and the dynamic array that stores the coefficients (real numbers).
The public methods include
a. default constructor that sets the value of x to zero and the order to 0,
b. a two argument constructor that takes as arguments the value of x and the order of the polynomial. The values of the coefficients are set to zero.
c. inputCoefficients(): prompts the user to input the value of the coefficients of the polynomial. For this homework, skip the user input. Instead assign the coefficent values equal to the index of the position in the array. For example, a0 = 0, a1 = 1, a2 = 2 and so on depending on the order of the particular polynomial object
c. a copy constructor
d. << operator overloaded that returns the value of the polynomial (obtained by evaluating the polynomial).
e. == overloaded (copy assignment operator)
f. destructor. Deallocates dynamic arrays and prints a message "Polynomial destroyed! "
Below is the testing program -
*/
#include <iostream>
using std::cin;
using std::endl;
using std::cout;
#include <cmath>
class Polynomial {
public:
Polynomial() {
x = 0,
order = 0;
coefficents = new double[order + 1];
}
Polynomial(const double x, const int order) {
this->x = x;
this->order = order;
this->coefficents = new double[order + 1];
for(int i = 0; i <= order; ++i)
this->coefficents[i] = 0;
}
Polynomial(const Polynomial& p) {
this->x = p.x;
this->order = p.order;
this->coefficents = new double[this->order];
for(int i = 0; i <= this->order; ++i)
this->coefficents[i] = p.coefficents[i];
}
~Polynomial() {
std::cout << "Polynomial destroyed! " << std::endl;
delete[] coefficents;
}
void inputCoefficients() {
/*
for(auto& num: coefficents) {
std::cout << "Enter the next coefficent:: ";
std::cin >> num;
}
std::cout << "Thank you" << std::endl;
*/
for(int i = 0; i <= order; ++i) {
coefficents[i] = i;
}
}
Polynomial& operator = (const Polynomial& p) {
this->x = p.x;
this->order = p.order;
delete[] this->coefficents;
this->coefficents = new double[order + 1];
for(int i = 0; i <= this->order; ++i)
this->coefficents[i] = p.coefficents[i];
return *this;
}
friend std::ostream& operator << (std::ostream& out, Polynomial& p);
friend bool operator == (const Polynomial& p1, const Polynomial& p2);
private:
double x;
double* coefficents;
int order;
};
std::ostream& operator << (std::ostream& out, Polynomial& p) {
double ans;
for(int i = 0; i <= p.order; ++i)
ans += (double)p.coefficents[i] * pow(p.x, i);
out << ans;
return out;
}
bool operator == (const Polynomial& p1, const Polynomial& p2) {
if((p1.x != p2.x) && (p1.order != p2.order))
return false;
for(int i = 0; i < p1.order; ++i) {
if(p1.coefficents[i] != p2.coefficents[i])
return false;
}
return true;
}
int main ()
{
Polynomial p1 (0.5,3); // Invokes two argument constructor for p1
p1.inputCoefficients(); // Set the coefficient of polynomial p1
cout << "Polynomial p1 evaluates to " << p1 << endl;
Polynomial p2(p1), p3; // Copy constructor for p2 and default constructor for p3
cout << "Polynomial p2 evaluates to " << p2 << endl;
cout << "Polynomial p3 evaluates to " << p3 << endl;
p3 = p2; // Copy assignment operator
return 0;
}
Your << function contains the line:
ans += (double)p.coefficents[i] * pow(p.x, i);
If you don't initialize ans to 0, then the initial value of ans will be indeterminate, and then you're adding each term to this. So you get a random result.
In your case, ans is apparently holding on to its value from the previous call. And since p3 is an empty polynomial, the loop never adds anything to it, so you print the previous result.
I need to add obejcts to a list (for now they are just hard coded objects in main)
int main ()
{
// create objects of type Point, passing different x and y values to the contructor
Point point1 (7,5); // new point object point1 with value x=2.5, y=5.3
Point point2 (4,8); // second point obejct
Point point3 (8,9); // third point object
Point point4 (10,5);//fourth point object
Point point5 (6,8);//fifth point
Point point6 (4,7);//sixth point
}
add them to a list one by one using push_back
list<Point>pointList ; // stl list that will contain my objects.
pointList.push_back(point1);//adds the obejcts to the list from the back each time {point1}
pointList.push_back(point2);//{point1, point2} < point2 pushed_back
pointList.push_back(point3);//{point, point}
pointList.push_back(point4);
pointList.push_back(point5);
pointList.push_back(point6);
now what i need to do is pass objects 3 at a time to this method >
static void calculateF (Point p1, Point& p2, Point p3)// point2 needs to be a reference otherwise f is just changed locally.
double F ; //
double xPoint1 = p1.getX(); // x value of object p1
double yPoint1 = p1.getY(); // y value of object p1
double xPoint2 = p2.getX(); // x value of object p2
double yPoint2 = p2.getY(); // y coordinates of object p2
double xPoint3 = p3.getX(); // x coordinates of obejct p3
double yPoint3 = p3.getY(); // y coorinates of obejct p3
//equation for working out f from these six values
//temp variables to store the length of the triangles sides.
double p2p3 = sqrt (((xPoint2 - xPoint3)*(xPoint2 - xPoint3)) + ((yPoint2 - yPoint3)*(yPoint2 - yPoint3))); //length point2 to point1 (PR in assingment notes)
cout << "p1p2 is = " << p2p3 << endl; // print the value of p2p3 (PR)
double p1p2 = sqrt (((xPoint1 - xPoint2)*(xPoint1 - xPoint2)) + ((yPoint1 - yPoint2)*(yPoint1 - yPoint2))); //length point1 to point 2 (LP in assingment notes)
cout << "p1p2 is = " << p1p2 << endl;
double p1p3 = sqrt (((xPoint1 - xPoint3)*(xPoint1 - xPoint3)) + ((yPoint1 - yPoint3)*(yPoint1 - yPoint3)));//length of point1 to point 3 (LR in assigment notes)
cout << "hypotenuse p1p3 is = " << p1p3 << endl;
F = p1p2 + p2p3 - p1p3 ; //equation for f
//cout << "importance factor is " << F << endl ;
p2.setF(F); // setting F to f in class
}
now i understand that i could just pass one at a time like
calculatef(point1,point2,point3);
calculatef(point2.point3,point4);
etc..............
its not actually using the list at all to pass them, which is what i need to do. Add points the the list and use the list to pass each point to the calculateF method.
If thats a really round about way of asking the question i apoligise. I just included everything so it could be put into context.
Thanks in advance competent programmers
You can also do something more generic with vector-iterators, like;
void calculateF (std::vector<Point>::iterator from_a,
std::vector<Point>::iterator to_b )
{
for (std::vector<Point>::iterator i=from_a; i != to_b; ++i) {
// ... do something with i->x and i->y
}
}
main()
{
...
calculateF(vec.begin()+0, vec.begin()+3);
calculateF(vec.begin()+3, vec.begin()+6);
...
}
Since a list is implemented as a doubly linked list you may be better suited using a vector (as you can gain access to individual elements very easily and efficiently using a vector...).
You could use the following code example in order to perform what you wish
std::vector<Point> vec;
vec.push_back( Point(0,0));
// Push back all other points...
for( int i = 0; i < ( vec.size() - 2 ); i++ )
{
calculateF( vec[i], vec[i+1], vec[i+2] );
}
I hope this helps...