So I'm working with operator overloading and just realized that my negation operator isn't working as it should be. I'm not exactly sure what I've done wrong.
The .h signature
Vector & Vector::operator-()
The .cpp implementation
Vector & Vector::operator-()
{
pVec[0] = -pVec[0];
pVec[1] = -pVec[1];
pVec[2] = -pVec[2];
return *this;
};
Calling:
cout << "-Vector E = " << -VecE << (-VecE).Magnitude() << endl << endl;
The variables in VecE are like [0, 1 , 1] which means when this is called it should display them as [0, -1, -1] but it's not. So what am I missing?
EDIT: Adding copy constructor and iostream<< overload code:
Vector::Vector(const Vector & Copy)
{
pVec = new double[3];
if (0 == pVec)
{
exit(1);
}
else
{
pVec[0] = Copy.pVec[0];
pVec[1] = Copy.pVec[1];
pVec[2] = Copy.pVec[2];
}
};
ostream & operator<<(ostream & Out, Vector & RHS)
{
cout.precision(1);
Out << fixed << "[ " << RHS.pVec[0] << " " << RHS.pVec[1] << " " << RHS.pVec[2] << " ]" << resetiosflags (ios_base::fixed);
return Out;
};
You need to return a copy of the vector. The way this is written, the expression -VecE will actually modify VecE! Since you evaluate -VecE twice, you are negating the vector twice, and (of course) the negation of the negation is the original value.
To implement this change, you need to alter the operator-() declaration to return a Vector instead of a Vector &.
For example:
Vector Vector::operator-()
{
Vector copy(*this);
copy.pVec[0] = -copy.pVec[0];
copy.pVec[1] = -copy.pVec[1];
copy.pVec[2] = -copy.pVec[2];
return copy;
};
cdhowie is right. You are negating twice.
That said, I don't think you need to change the implementation.
Vector const NegVecE = -VecE;
cout << "-Vector E = " << NegVecE << NegVecE.Magnitude() << endl << endl;
EDIT: As PiotrNycz notes, though this will work, the end state is un-intuitive and therefore the correct solution is to return a copy.
{
int i = 3;
int j = -i; //you would expect i to still be 3 here
}
Related
Consider this code:
# include <iostream>
using namespace std;
int main()
{
for(int i = 5; i>0;)
{
i--;
cout <<i<<" ";
}
return 0;
}
The output of this code would be 4 3 2 1 0.
Can I change the decrement/increment value?
In detail, this means that the default decrement/increment value is 1. So you either minus 1 or add 1.
Can I change it to minus 0.2 or add 1.3?
If so, is there a way to tell the compiler that I want to change the -- value from 1 to 0.2 and still using the -- operator instead of changing it to -= 0.2?
d-- is shorthand for d -= 1, which is shorthand for d = d - 1.
You should not read this as a mathematical equation, but as "calculate d - 1 and assign the result as the new value of d".
#include <iostream>
int main()
{
float day = 1.2;
for(int i = 0; i < 5; i++)
{
day -= 0.2;
std::cout << day;
}
return 0;
}
(I also removed using namespace std as it is bad practice).
Note the second part of the for loop is a condition that keeps the loop going as long as it is true. In your case, i > 5 is false from the beginning (because 0 < 5) so the loop will never run. I assumed you meant i < 5 instead.
i-- is the post-fix decrement operator. For builtin types it means that i is decremented by one (1). The value of the expression i-- is the value of i before decrementing it.
--i is the pre-fix decrement operator. For builtin types it means that i is decremented by one (1). The value of the expression --i is the value of i after decrementing it.
For the builtin types you cannot change the behaviour of the increment or decrement operators. If you want to have another behaviour, you need to fallback to the operators += and -= where you can add whatever you want. But please note that your code used int and you probably want to change to float or double first before adding or subtracting 0.1 or 0.2.
You can change the behaviour for increment and decrement operators for your own types, though. Here is an exammple
#include <iostream>
struct S {
S& operator++() { // prefix increment "++s"
d += increment_value;
return *this;
}
S& operator--() { // prefix decrement "--s"
d -= decrement_value;
return *this;
}
S operator++(int) { // postfix increment "s++"
S copy{*this};
d += increment_value;
return copy;
}
S operator--(int) { // postfix decrement "s--"
S copy{*this};
d -= decrement_value;
return copy;
}
double d{};
double increment_value{0.2};
double decrement_value{0.1};
friend std::ostream& operator<<(std::ostream& os, const S& s) {
os << s.d;
return os;
}
};
int main(int, char**) {
S s{1};
std::cout << "val=" << s.d << '\n';
std::cout << "prefix++=" << ++s << '\n';
;
std::cout << "val=" << s.d << '\n';
std::cout << "postfix++=" << s++ << '\n';
std::cout << "val=" << s.d << '\n';
std::cout << "prefix--=" << --s << '\n';
std::cout << "val=" << s.d << '\n';
std::cout << "postfix--=" << s-- << '\n';
std::cout << "val=" << s.d << '\n';
}
The output is
val=1
prefix++=1.2
val=1.2
postfix++=1.2
val=1.4
prefix--=1.3
val=1.3
postfix--=1.3
val=1.2
You might notice that I added two operator ++ and two operator--. One of each is getting no parameter, the other is getting an int. As cppreference describes, the int parameter is only a dummy parameter to differentiate between the prefix and the postfix versions of the operators. (*)
As you can also see, the prefix operators are more performant as they don't need the extra copy. So normally please use the prefix versions (compare the CppCoreGuidelines).
But, please ignore the possibility to change the increment and decrement operators. It is counter intuitive and only a source of errors and head aches. Don't do it this way!
(*) This parameter could also be used for even more confusing behaviour, but it should be clear that this is making the idea even worse. So see this just as an example of what is technically possible.
#include <iostream>
struct S {
S operator++(int diff) { // postfix increment "s++", diff defaults to zero (0)
S copy{*this};
d += diff ? diff : increment_value;
return copy;
}
S operator--(int diff) { // postfix decrement "s--", diff defaults to zero (0)
S copy{*this};
d -= diff ? diff : decrement_value;
return copy;
}
double d{};
double increment_value{0.2};
double decrement_value{0.1};
friend std::ostream& operator<<(std::ostream& os, const S& s) {
os << s.d;
return os;
}
};
int main(int, char**) {
S s{1};
std::cout << "val=" << s.d << '\n';
s++;
std::cout << "val=" << s.d << '\n';
s.operator++(2);
std::cout << "val=" << s.d << '\n';
s--;
std::cout << "val=" << s.d << '\n';
s.operator--(2);
std::cout << "val=" << s.d << '\n';
}
results in
val=1
val=1.2
val=3.2
val=3.1
val=1.1
You can change the loop variable both inside the for and the body any way you like. For example:
for (double d = 4; d > 0; d = cos(d) + 1 / d) {
d = sin(d);
std::cout << d << " ";
}
C++ does not have a fixed count loop like other languages for i = 0 to 10 do ... done where the i can not be changed. Do whatever you like.
Note: I change the type to double since you asked about decrementing by 0.2. The type int doesn't allow that.
Can I change the decrement/increment value?
Yes, that is what the third parameter(?) in the for loop does.
#include <iostream>
int main()
{
for(int i = 5; i > 0; i -= 2)
{
std::cout << i << std::endl;
}
return 0;
}
Can I change it to minus 0.2 or add 1.3?
Yes, you'd simply change the first parameter to be a float and the third parameter to decrement/increment by whatever you'd like.
#include <iostream>
int main()
{
for (float i = 5; i > 0; i -= .2)
{
std::cout << i << std::endl;
}
return 0;
}
If I understand correctly what you want to do is to change the behavior of T operator --();.
You can do that with your own type:
struct Foo {
float boat;
auto operator --() noexcept { return boat -= .2f; }
operator float() const noexcept { return boat; }
};
#include <cstdio>
int main() {
for (Foo i{ 5 }; i > 0; --i) {
std::printf("%1.2f, ", static_cast<float> (i));
}
}
Live on Compiler Explorer
Should you ever do that? No, you shouldn't. But now you know how not to do it should the opportunity not come.
I'm trying to overload a copy assignment operator in template struct xpair
template <typename First, typename Second>
struct xpair {
First first{};
Second second{};
xpair(){}
xpair (const First& first, const Second& second):
first(first), second(second) {}
xpair& operator= (const xpair& that) {
cout << "*this = " << *this << " " << "that = " << that << endl;
cout << "use operator = " << endl;
*this = that;
return *this;
}
};
But when I test this code with
using commend = string;
using str_str_pair = xpair<string, string>;
using commend_pair = xpair<commend, str_str_pair>;
commend_pair cmd_pair;
str_str_pair str_pair("a", "1");
commend cmd("comment");
cmd_pair.first = cmd;
cmd_pair.second = str_pair;
It gives me infinite output as
use operator =
*this = {,} that = {a,1}
use operator =
*this = {,} that = {a,1}
use operator =
*this = {,} that = {a,1}
use operator =
*this = {,} that = {a,1}
Why is that?
It gives me infinite output as
Why is that?
Because you've defined the function in terms of itself, see the following code comment.
xpair& operator= (const xpair& that)
{
cout << "*this = " << *this << " " << "that = " << that << endl;
cout << "use operator = " << endl;
// Here you're asking for `this` (i.e., an `xpair` type) to be assigned
// a `that` (i.e., another `xpair` type) using the `operator=` which is
// the function currently being implemented/defined. A function calling
// itself is recursion and there is no stopping condition so it will
// continue infinitely.
*this = that;
return *this;
}
Instead your operation should set the data members of this instance using the data members of that instance.
xpair& operator= (const xpair& that)
{
cout << "*this = " << *this << " " << "that = " << that << endl;
cout << "use operator = " << endl;
first = that.first;
second = that.second;
return *this;
}
Your line
*this = that;
is an assignment as well, taking two arguments. And both are xpair<First,Second>, so it calls the same operator again.
What you would probably like to do is this:
this->first = that.first;
this->second = that.second;
which calls the assignment operators for First and Second.
Your problem is, as others have noted, that your operator= calls your operator=. This results in an infinite recursion.
But, I'll argue for a different implementation:
Add this:
template<class Self,
class=std::enable_if_t<std::is_same<std::decay_t<Self>, xpair>{}>
>
friend auto tieme(Self&& self) {
return std::forward_as_tuple(
std::forward<Self>(self).first,
std::forward<Self>(self).second
);
}
to the body of your pair. The enable_if_t stuff is a bit obscure, but it makes sure this free function will only be invoked on genuine xpairs.
Now your operator= is just:
xpair& operator= (const xpair& that) {
tieme(*this)=tieme(that);
return *this;
}
which is nice, because you don't have to repeat the order of your elements twice over.
But it doesn't stop there.
friend bool operator<(const xpair& lhs, const xpair& rhs) {
return tieme(lhs) < tieme(rhs);
}
the same technique lets you write a bunch of other operators. And anyone who has ever had bugs in < boilerplate will understand that the above is nice.
Move assign?
xpair& operator= (xpair&& that) {
tieme(*this)=tieme(std::move(that));
return *this;
}
swap?
friend void swap(xpair& lhs, xpair& rhs) {
std::swap( tieme(lhs), tieme(rhs) );
}
and it scales -- add more stuff to tieme, and it is auto-handled by all your other methods.
As I specified in the title, this is a problem that puzzled me enormously, and still I can not find a fix for it.
I created a Point class which has three private attributes (_id, _x and _y) with related public get and set methods.
For example, I created three points (G, H, R), where the point G is a "parent". Point H is the prototype of the point G (a clone) and point R will be the outcome of the meeting points (G+H) (addition of the points).
Points sample:
Point G ("pG", 3.5f, 6.5f);
Point H (G.prototype ()); H.setId ("pH");
Point R;
R = G + H;
The program works correctly, but unfortunately after the operation {R=G+H}, _id attribute of point G becomes the clone attribute of point R, I do not understand why this is happening because the evaluation is done from right to left (H+, +G, =R).
The question is why G point attribute changes itself?
Code where the problem occurs:
#include <iostream>
#include <string>
using namespace std;
class Point
{
private:
string _id;
double _x;
double _y;
public:
Point(string id="undefined", double x = 0.00f, double y = 0.00f)
:_id(id), _x(x), _y(y){}
~Point(){}
public:
// Getters methods
string getId() const { return _id;}
double getX() const { return _x; }
double getY() const { return _y; }
void setId(string id) { _id = id; }
// Setters methods
void setX(double n = 0.00f) { _x = n; }
void setY(double n = 0.00f) { _y = n; }
Point prototype() { return Point(_id, _x, _y); }
Point operator+ (const Point& p)
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
_id.append("+").append(p._id),
_x+p._x,
_y+p._y
);
}
Point operator= (const Point& p)
{
cout << "Operator = called, returning a new object Point(p._id, p._x, p._y)" << endl;
_id=p._id;
_x=p._x;
_y=p._y;
return *this;
}
};
int main()
{
Point G("G",10.0f, 10.0f);
Point H(G.prototype()); H.setId("H");
Point R;
R = G + H;
cout << "object Point {id: " << G.getId() << ", x: " << G.getX() << ", y: " << G.getY() << "}" << endl;
cout << "object Point {id: " << H.getId() << ", x: " << H.getX() << ", y: " << H.getY() << "}" << endl;
cout << "object Point {id: " << R.getId() << ", x: " << R.getX() << ", y: " << R.getY() << "}" << endl;
return 0;
}
Thanks in advance!
Point operator+ (const Point& p)
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
_id.append("+").append(p._id), // HERE
_x+p._x,
_y+p._y
);
}
In this line, you modify _id property of this object. As a rule of thumb, binary + operator should be a const member or - IMO cleaner - a static method taking two const reference arguments.
BTW, you can add strings in C++ by just applying + operator to them (_id + "+" + p._id).
If you implement your binary arithmetic operators as members, you should consider making the operator a const member. This would catch the obvious modification in your implementation (the implementation is made out of line to avoid including unrelated code):
Point Point::operator+ (const Point& p) const
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
_id.append("+").append(p._id),
_x+p._x,
_y+p._y
);
}
The operation _id.append("+") actually operates on this->_id, i.e., the _id member of the left hand operand. Since you member operator isn't const, the compiler lets you do the modification. This is probably not what you intended to do. You probably rather wanted to write:
Point Point::operator+ (const Point& p) const
{
cout << "Operator + called, returning a new object\n";
return Point
(
_id + "+" + p._id,
_x+p._x,
_y+p._y
);
}
... which creates a suitable temporary string with the desired value (I also replaced the excessive use of std::endl).
This line in the operator+ overload:
_id.append("+").append(p._id),
You have to be very careful here, you are currently in an object (in your example this would be the G object). append actually alters the local string, so your code is appending + then p._id then deep copying that to the returned value.
A quick fix is to change this to a temporary that holds what you need:
_id + "+" + p._id
To avoid problems like this in the future, you should declare operator overloads as a friend method so it's extremely clear what you're operating on.
friend Point operator+ (const Point& lhs, const Point& rhs)
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
lhs._id.append("+").append(rhs._id), //COMPILER ERROR! We're modifying the const "lhs"!
lhs._x+rhs._x,
lhs._y+rhs._y
);
}
So let's change this to:
friend Point operator+ (const Point& lhs, const Point& rhs)
{
cout << "Operator + called, returning a new object" << endl;
return Point
(
lhs._id + "+" + rhs._id, // no longer modifying lhs -- all is well!
lhs._x+rhs._x,
lhs._y+rhs._y
);
}
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
The printResults() method below (called from the main method at the bottom) returns -858993460 for all four values. Why is this? I have confirmed with cout statements that the numbers and calculations are correct within the doCalc() method, so I'm assuming the error is in the way I'm using pointers and calling the printResults() method...
typedef int matrix[2][2] ;
struct matrices {
matrix a;
matrix b;
};
...getInput() method constructs
matrix* doCalc (matrices m){
matrix toReturn;
char input;
cout << "Which calculation would you like to perform - (M)ultiply, (A)dd, (S)ubtract?";
cin >> input;
switch(input){
case 'M':
toReturn[0][0] = ((m.a[0][0])*(m.b[0][0]));
cout << "XX " << ((m.a[0][0])*(m.b[0][0]));
toReturn[0][1] = (m.a[0][1]*m.b[0][1]);
cout << "YY " << (m.a[0][1]*m.b[0][1]);
toReturn[1][0] = (m.a[1][0]*m.b[1][0]);
toReturn[1][1] = (m.a[1][1]*m.b[1][1]);
break;
case 'A':
toReturn[0][0] = (m.a[0][0]+m.b[0][0]);
toReturn[0][1] = (m.a[0][1]+m.b[0][1]);
toReturn[1][0] = (m.a[1][0]+m.b[1][0]);
toReturn[1][1] = (m.a[1][1]+m.b[1][1]);
break;
case 'S':
toReturn[0][0] = (m.a[0][0]-m.b[0][0]);
toReturn[0][1] = (m.a[0][1]-m.b[0][1]);
toReturn[1][0] = (m.a[1][0]-m.b[1][0]);
toReturn[1][1] = (m.a[1][1]-m.b[1][1]);
break;
}
return &toReturn;
}
void printResult(matrix m){
cout<<"---RESULT---\n";
cout << m[0][0] << " " << m[0][1] << "\n";
cout << m[1][0] << " " << m[1][1] << "\n";
}
void main() {
matrices m = getInput();
cout << m.a[0][0] << " " << m.a[0][1] << "\n";
cout << m.a[1][0] << " " << m.a[1][1] << "\n\n";
cout << m.b[0][0] << " " << m.b[0][1] << "\n";
cout << m.b[1][0] << " " << m.b[1][1] << "\n";
matrix* calc = doCalc(m);
matrix c = &calc;
printResult(*calc);
}
the matrix toReturn will be destroyed when the function exits, you will need to use some form of persistent memory allocation (look up new and delete). As such all the values are just nonsense.
matrix toReturn; is a local variable, allocated on the stack. After doCalc returns, its contents are undefined. In this case, the memory at its old address gets overwritten with random garbage.
toReturn will be destroyed with the stack frame when doCalc is finished.
Instead of returning the pointer pass it to the function you are calling.
void doCalc (matrices m, matrix* pReturnMatrix)
matrix* calc = new matrix();
doCalc(m, calc);
toReturn is a local variable in the doCalc function. It will no longer exist when the function returns.
An easy way to fix this is to pass a reference to the matrix that will store the result:
matrix* doCalc (matrices m, matrix& toReturn ){
Then remove this line from doCalc:
matrix toReturn;
And change how the function is called from this:
matrix* calc = doCalc(m);
matrix* calc = doCalc(m);
matrix c = &calc;
printResult(*calc);
To this:
matrix calc;
doCalc(m,calc);
printResult(calc);
There are other ways to fix this, e.g. new/delete as suggested in other places. However, now we will go into who allocates and who owns the memory. It won't be clear from the function signature alone who is responsible for what.
You can avoid managing dynamically allocated memory and requiring the caller supply an lvalue if you return by value.
matrix doCalc (const matrices& m)
{
matrix toReturn;
// Code here
return toReturn;
}
You can assign the results to a matrix object or use it in an expression like below.
if(doCalc(m).a[0][0] == 1)
{
// do something
}
or
matrix mat(doCalc(m));
if(mat.a[0][0] == 1)
{
// do something
}
I am new to cpp and have a situation in which I want to split array string
I have
for( i = k = 0; i < points[1].size(); i++ )
{
cout << points[1][k];
}
Output >>
[390.826, 69.2596]
[500.324, 92.9649]
[475.391, 132.093]
[5.60519e-44, 4.62428e-44]
I want
390.826
69.2596
500.324
92.9649
475.391
132.093
5.60519e-44
4.62428e-44
Please help me.Thanks
Assuming the type of point has public members x and y:
for( i = k = 0; i < points[1].size(); i++ )
{
cout << points[1][k].x << endl;
cout << points[1][k].y << endl;
}
If the members are something else, say, X and Y (the uppercase), then use the uppercase instead (or whatever it is).
The reason why you code prints the output that way, because operator<< has been overloaded for the type of the point. Something like:
std::ostream & operator<<(std::ostream & out, const point &p)
{
return out << "[" << p.x << "," << p.y << "]\n";
}
If you can search the above definition (or something similar) somewhere in your project source code, and then can change that to this:
std::ostream & operator<<(std::ostream & out, const point &p)
{
return out << p.x << "\n" << p.y << "\n";
}
then you wouldn't need to change the code in your for loop.
This has nothing to do with string splitting, what does points[1][k] actually return (i.e. it's type). Then look at how it has implemented the stream out operator (operator<<), and you'll see how the above is printed. This should give you a clue about the two individual values (i.e. fields of that *type), and you can simply access them and print them out.