Im pretty new to C++ and I have problem with pointers. Can someone please explain me how does this code return 0 for y, instead of 20?
#include <iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; cout << "hello"; return *this; }
Test setY(int b) { y = b; cout << "world"; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
}
Your methods are returning copies of the test object.
Test setX(int a) { x = a; cout << "hello"; return *this; }
Test setY(int b) { y = b; cout << "world"; return *this; }
So obj1.setX(10) applies to the original, but then .SetY(20) applies to the copy.
You need to return by reference:
Test& setX(int a) { x = a; cout << "hello"; return *this; }
Test& setY(int b) { y = b; cout << "world"; return *this; }
You are trying to implement a design called "function chaining". To do this, you must return a reference to the current object, not a brand new object:
Test& setX(int a) { x = a; cout << "hello"; return *this; }
Test& setY(int b) { y = b; cout << "world"; return *this; }
Since you are returning the current object, this will now work. Your example was returning a brand new Test object, which is why you were seeing 0 as the output.
If you want to chain calls to Test, your setters need to return a reference on Test instance.
If you do not return a reference to the object, it is not udpated, a copy of it is updated.
Without the reference what you wrote is equivalent to:
Test tmp = obj1.setX(10);
tmp.setY(20)
obj1.print()
(tmp is a "local" variable created by the compiler)
Fixed code below:
#include <iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test &setX(int a) { x = a; cout << "hello"; return *this; }
Test &setY(int b) { y = b; cout << "world"; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
Related
Let's say I have this as current code:
if (GetFlag(...)) {
if (auto x = GetX(...)) {
if (auto y = GetY(...)) {
...
}
}
}
and that the method calls and variable definitions need to be made in this order for both correctness and performance reasons (we don't want to calculate x if GetFlag(...) returns false, and we don't want to calculate y if x is nullptr).
Is there a way to refactor this into a "one-liner"? The closest I got to actually compiling would be
if (auto x = GetX(...); auto x = GetX(...) && GetFlag(...)) { ... }
but this does not preserve the order of operations.
Thanks!
You can extract the conditionals into a separate function that returns a tuple, and structured bind in the if
std::tuple<bool, std::optional<X>, std::optional<Y>> getFlagsXY()
{
if (!getFlags())
{
return { false };
}
if (auto x = getX(); !x)
{
return { true, std::move(x) };
}
else
{
return { true, std::move(x), getY() };
}
}
if (auto [f, x, y] = getFlagsXY(); f && *x && *y) { ... }
And yes it is possible.
If statements stop processing terms once they see which branch is going to be taken. Try changing the values of GetFlag, GetX to see when the body of the if gets called.
#include <iostream>
bool GetFlag()
{
std::cout << "GetFlag\n";
return true;
}
int GetX()
{
std::cout << "GetX\n";
return 0;
}
int GetY()
{
std::cout << "GetY\n";
return 3;
}
int main()
{
int x;
int y;
if (GetFlag() && (x = GetX()) && (y = GetY()))
{
std::cout << "Do " << x << ", " << y;
}
return 0;
}
as follows
#include <iostream>
using namespace std;
class A
{
public:
int val;
A(int n)
{
val = n;
}
A()
{
val = 123;
}
int &GetObj()
{
return val;
}
int operator=(const A &a)
{
return a.val;
}
};
int main()
{
int m, n;
A a;
cout << a.val << endl;
while (cin >> m >> n)
{
a.GetObj() = m;
cout << a.val << endl;
a.GetObj() = A(n);
cout << a.val << endl;
}
return 0;
}
everytime ERROR appeared instantly when i tried to compile the program .remaining the main fuction unchanged,how can i modify the program to make sure itll pass? maybe i should focus on a constructor or type of GetObj?
You can do that by overloading the "cast operator"…
struct A {
int val;
A(int i) : val{ i } {}
operator int() const { return val; }
A& operator=(int i) { val = i; return *this; }
};
int main() {
A a = 10; // A::A(int)
int i = a; // A::operator int() const
a = 11; // A::operator =(int)
return a - i; // implicit conversion of A to int
}
Live example
I have written a program which was given to me as a homework assignment (it's a bit longer). The issue is that it compiles in CodeBlocks but it does not compile in Visual Studio 2017 it says - binary '=': no operator found which takes a right-hand operand of type 'CAutomobile' (or there is no acceptable conversion.
I would like to ask why is that because I could not myself find the error? I tried commenting the operator =function but still the error remained.
#include <iostream>
#include <algorithm>
#include <string>
#include <stdlib.h>
using namespace std;
class CVehicle {
string name;
int year;
public:
CVehicle() {
name = "Car";
year = 1990;
}
CVehicle(string n, int y) {
name = n;
year = y;
}
CVehicle(const CVehicle& vc) {
name = vc.name;
year = vc.year;
}
void setName(string n) {
name = n;
}
void setYear(int y) {
year = y;
}
string getName() {
return name;
}
int& getYear() {
return year;
}
virtual void Print(ostream& os) = 0;
};
class CAutomobile :public CVehicle {
double litres;
public:
CAutomobile() :CVehicle() {
litres = 7.2;
}
CAutomobile(string nm, int yr, double l) :CVehicle(nm, yr) {
litres = l;
}
void setLitres(double l) {
l = litres;
}
double& getLitres() {
return litres;
}
void Print(ostream& os) override {
os << getName() << endl;
os << getYear() << endl;
os << litres << endl;
}
friend bool operator< (CAutomobile a1, CAutomobile a2) {
if (a1.litres < a2.litres) {
return true;
}
return false;
}
CAutomobile operator= (CAutomobile& at) {
CAutomobile au;
au.getName() = at.getName();
au.getYear() = at.getYear();
au.getLitres() = at.getLitres();
return au;
}
CAutomobile operator+(CAutomobile aut) {
CAutomobile a;
a.getLitres() = getLitres() + aut.getLitres();
return a;
}
friend ostream& operator<< (ostream& o, CAutomobile a) {
o << a.getName() << endl;
o << a.getYear() << endl;
o << a.getLitres() << endl;
return o;
}
};
int main()
{
CAutomobile a[] = {
CAutomobile(),
CAutomobile("Wolkswagen",1970,80.5),
CAutomobile("Fiat",1979,21.9),
CAutomobile("Opel",1978,13.7)
};
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
cout << "Name" << ' ' << a[i].getName() << endl;
cout << "Year" << ' ' << a[i].getYear() << endl;
cout << "Litres" << ' ' << a[i].getLitres() << endl;
}
int range = 2016 - 1990 + 1;
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
a[i].setLitres(rand() % 100 + 1);
a[i].setYear(rand() % range + 1996);
}
//сортираме масива по литри и извеждаме
//най малкия (първия) му елемент
for (int i = 0; i < sizeof(a-1); i++) {
for (int j = 0; j < sizeof(a-1); j++) {
if (a[j].getLitres() > a[j + 1].getLitres()) {
swap(a[j], a[j + 1]);
}
}
}
cout << a[0] << endl;
CAutomobile k = a[0] + a[3];
cout << k.getLitres() << endl;
}
CAutomobile::operator = is completely wrong. It takes a non-const reference and assignes its field to a new object. Instead it should take a const reference and modify current object.
CAutomobile & operator =(CAutomobile const & other)
{
assert(this != ::std::addressof(other)); // check for self-assignment
SetName(other.getName());
SetYear(other.getYear());
SetLitres(other.getLitres());
return *this;
}
This will bring up another problem: getters are not const-qualified, so they should be fixes as well:
string const & getName(void) const {
return name;
}
int const & getYear(void) const {
return year;
}
The problem:
#include <iostream>
#include <algorithm>
using namespace std;
struct abc
{
int cost;
int any;
};
int main() {
abc *var1 = new abc[5];
var1[0].cost = 4;
var1[1].cost = 42;
var1[2].cost = 5;
var1[3].cost = 0;
var1[4].cost = 12;
// cout<< "value = " << *std::min_element(var1.cost,var1.cost+5) << endl;
// cout << "Position = " << (std::min_element(var1.cost,var1.cost+5)-var1.cost) << endl;
return 0;
}
How to find minimum value and position of var1[].cost? is it possible to find this using std::min_element?
std::min_element - cppreference.com
You can use a comparision function object to have std::min_element look at the member cost.
#include <iostream>
#include <algorithm>
using namespace std;
struct abc
{
int cost;
int any;
};
struct cmp_abc {
bool operator()(const abc& a, const abc& b) const {
return a.cost < b.cost;
}
};
int main() {
abc *var1 = new abc[5];
var1[0].cost = 4;
var1[1].cost = 42;
var1[2].cost = 5;
var1[3].cost = 0;
var1[4].cost = 12;
abc *res = std::min_element(var1, var1 + 5, cmp_abc());
cout << "value = " << res->cost << endl;
cout << "Position = " << (res - var1) << endl;
delete[] var1;
return 0;
}
I can think of at least four ways to do this with std::min_element
1) Add a "less than" member function to the struct/class:
struct abc
{
int cost;
int any;
bool operator<(const abc &other) const { // member function
return cost < other.cost;
}
};
int main() {
// ...
// The algorithm will find and use the class operator< by default
abc *ptr = std::min_element(var1, var1 + 5);
}
2) Define a free function:
bool abc_less(const abc &lhs, const abc &rhs) // free function
{
return lhs.cost < rhs.cost;
}
int main() {
// ...
// Pass a function pointer to the algorithm
abc *ptr = std::min_element(var1, var1 + 5, abc_less);
}
3) Define a function object type:
struct abc_less // function object
{
bool operator()(const abc &lhs, const abc &rhs) const {
return lhs.cost < rhs.cost;
}
};
int main() {
// ...
// Construct and pass a function object to the algorithm
abc *ptr = std::min_element(var1, var1 + 5, abc_less());
}
4) Create a lambda function:
int main() {
// ...
// Create a lambda at the point of call in this example
abc *ptr = std::min_element(var1, var1 + 5, [](const abc &lhs, const abc &rhs) { return lhs.cost < rhs.cost; });
}
Finally, use the returned iterator (pointer in this case) to print the value or offset:
std::cout << "Value = " << ptr->cost << '\n';
std::cout << "Position = " << (ptr - var1) << '\n'; // or std::distance(var1, ptr)
Why is this code not valid?
void callbyreference (int& adam) {
cout << adam << endl;
}
int main() {
int *beta = new int();
*beta = 34;
callbyreference(beta);
}
Because beta is a pointer to int, but callbyreference doesn't take a pointer parameter - it takes a reference.
References are not pointers.
You can say either
void callbyreference (int* adam) {
cout << *adam << endl;
}
int main() {
int *beta = new int();
*beta = 34;
callbyreference(beta);
}
or
void callbyreference (int& adam) {
cout << adam << endl;
}
int main() {
int beta = 34;
callbyreference(beta);
}
void callbyreference (int& adam) {
cout << adam << endl;
}
int main() {
int *beta = new int();
*beta = 34;
callbyreference(*beta);
}