How do I set multiple class members in one statement in C++? - c++

Is it possible to set multiple different class members in one statement? Just an example of how this would be done:
class Animal
{
public:
int x;
int y;
int z;
};
void main()
{
Animal anml;
anml = { x = 5, y = 10, z = 15 };
}

To "convert" Barry's comment into an answer, yes, under the conditions here:
An aggregate is an array or a class (clause 9) with no user-declared
constructors (12.1), no private or protected non-static data members
(clause 11), no base classes (clause 10), and no virtual functions
(10.3).
Example:
class Animal
{
public:
int x;
int y;
int z;
};
int main() {
Animal anml;
anml = { 5, 10, 15 };
return 0;
}
(This Community Wiki answer was added in accordance with this meta post.)

You can always overload constructors or create methods that "set multiple different object properties in one statement":
class Animal {
public:
Animal() {
};
Animal(int a, int b, int c) {
x = a;
y = b;
z = c;
}
void setMembers(int a, int b, int c) {
x = a;
y = b;
z = c;
}
private:
int x;
int y;
int z;
};
int main() {
// set x, y, z in one statement
Animal a(1, 2, 3);
// set x, y, z in one statement
a.setMembers(4, 5, 6);
return 0;
}

Solution 1 for Animal (http://ideone.com/N3RXXx)
#include <iostream>
class Animal
{
public:
int x;
int y;
int z;
Animal & setx(int v) { x = v; return *this;}
Animal & sety(int v) { y = v; return *this;}
Animal & setz(int v) { z = v; return *this;}
};
int main() {
Animal anml;
anml.setx(5).sety(6).setz(7);
std::cout << anml.x << ", " << anml.y << ", " << anml.z << std::endl;
return 0;
}
Solution 2 for any class with x, y (https://ideone.com/xIYqZY)
#include <iostream>
class Animal
{
public:
int x;
int y;
int z;
};
template<class T, class R> T& setx(T & obj, R x) { obj.x = x; return obj;}
template<class T, class R> T& sety(T & obj, R y) { obj.y = y; return obj;}
int main() {
Animal anml;
sety(setx(anml, 5), 6);
std::cout << anml.x << ", " << anml.y << std::endl;
return 0;
}

Related

How I can prevent an instance from invoking the constructor in C++?

I have a sample of code like this:
class A {
int x{0};
int y{0};
public:
/* A() {}; */
A(int x, int y)
{
this->x = x;
this->y = y;
};
A operator+(A const &);
};
A A::operator+(A const &tmp)
{
A t; // HERE
t.x = this->x + tmp.x;
t.y = this->y + tmp.y;
return t;
};
int main(void)
{
A a = {1, 2};
A b = {3, 4};
A c = a+b;
}
And inside the body of A::operator+ I have this object t, and I wanna prevent this object from invoking A::A() constructor instead of initializing it as: A t(0, 0);. Is this possible in C++?

Why is my C++ program's copy constructor called twice?

I can't figure out why my output start with "ACCB.." - my expectation was "ACB.."
Why is the copy constructor of class A called twice?
#include <iostream>
using namespace std;
class A
{
int x, y, z;
public:
A(int x, int y, int z) :x(x), y(y), z(z) { cout << "A"; }
A(A& a) :x(a.x), y(a.y), z(a.z) { cout << "C"; }
void sh() { cout << x << y << z; }
};
class B
{
A a;
int q, r;
public:
B(A x, int y, int z) : a(x), q(y), r(z) { cout << "B"; }
void sh() { a.sh(); cout << q << r; }
};
int main()
{
A i(9, 7, 4);
B b(i, 3, 7);
b.sh();
}
Your copy constructor is being called 2 times because you are making 2 copies. 1 is being made implicitly by the compiler, and 1 is being made explicitly in your own code.
In your B constructor, its x parameter is being passed by value. That is an implicit copy being made when i in main() is assigned to x. Then, an explicit copy is made when x is passed to the copy constructor of the a member of B.
You can eliminate the implicit copy by changing the x parameter to be passed by reference instead.
Also, your A copy constructor should be declared as A(const A& a).
#include <iostream>
using namespace std;
class A
{
int x, y, z;
public:
A(int x, int y, int z) :x(x), y(y), z(z) { cout << "A"; }
A(const A& a) :x(a.x), y(a.y), z(a.z) { cout << "C"; }
void sh() { cout << x << y << z; }
};
class B {
A a;
int q, r;
public:
B(const A& x, int y, int z) : a(x), q(y), r(z) { cout << "B"; }
void sh() { a.sh(); cout << q << r; }
};
int main()
{
A i(9, 7, 4);
B b(i, 3, 7);
b.sh();
}
Why copy constructor of class A is called twice?
Because your B constructor takes its first argument (an object of class A) by value - so a copy of i is made, which is then passed to the constructor.
To prevent this, declare the first argument to the B constructor as a reference (as in the A copy constructor itself):
B(A& x, int y, int z) : a(x), q(y), r(z)
{
cout << "B";
}

Can you construct after instantiation? Avoiding empty constructor

I have a class which has a member attribute consisting of an object defined elsewhere. In the code below, A contains a public attribute var which is a B:
class B {
public:
int x, y;
std::vector<int> z;
B(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
B var;
A(int i, int j) {
std::vector<int> someVector;
B(i, j, someVector);
}
};
int main() {
A foo(5, 3);
return 0;
}
This (obviously) doesn't compile as var is instantiated upon an instantiation of A, too late for it to be constructed.
The best way I can do something similar is modify some code:
class B {
public:
int x, y;
std::vector<int> z;
B() {}
void setAttributes(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
B var;
A(int i, int j) {
std::vector<int> someVector;
B.setAttributes(i, j, someVector);
}
};
This does compile because attributes are set after instantiation.
But is there a way to remain closer to the first code snippet?
A(int i, int j) : var(i, j, {}) {}
Also, in your code B(i, j, someVector); does not initialize member variable var, and B.setAttributes(i, j, someVector); wouldn't compile at all.
if you cannot define a useful default constructor and don't want the ugly two step initialization, I guess there is no way around a pointer to B. Something like
#include <memory>
class B {
public:
int x, y;
std::vector<int> z;
B(int a, int b, std::vector<int> c) {
x = a; y = b; z = c;
}
};
class A {
public:
std::unique_ptr<B> var;
A() {
std::vector<int> someVector;
var = std::make_unique<B>(5, 2, someVector);
}
};
int main() {
A foo();
return 0;
}
should do the trick.

I am not able to use a friend function properly

I am writing a code to declare a member function of a class as a friend, but I am getting errors.
The code is
#include<iostream>
class Vect;
class Coordinate {
float x;
float y;
public:
Coordinate(float a,float b):x(a),y(b){}// constructor
Coordinate():x(0),y(0){};//constructor
display()
{
std::cout<<"\nx:"<<x<<" "<<"y:"<<y;
}
friend Vect::add(Coordinate B);
};
class Vect {
public:
add(Coordinate A)
{
std::cout<<A.x;
}
};
The exact errors are
invalid use of incomplete type 'class Vect'| and forward declaration
of 'class Vect'|
class Y; //forward declaration of class Y
class X
{
public:
int getmark(Y);
};
class Y
{
int mark;
public:
Y() {}
friend int X::getmark(Y);
};
int X::getmark(Y obj) {
cin >> obj.mark;
return obj.mark;
}
int main()
{
X a;
Y b;
a.getmark(b);
}
At first, when the object a (class X) is created, a forward declaration of class Y is necessary in order to declare the Y argument to X::getmark().
Creating object b (class Y) wont be a problem as the compiler knows class X exists (for the friend function).
Then, simply call the function getmark() through the object a.
Note: It is necessary to declare the function getmark() after the declaration of class Y, or else compiler will consider the class Y as an incomplete type.
you can use this :
class Vect;
class Coordinate
{
public:
Coordinate(float a = 0f, float b = 0f) :x(a), y(b) {}// constructor
float x;
float y;
void display()
{
std::cout << "\nx:" << x << " " << "y:" << y;
}
friend int add(Coordinate B);
};
class Vect
{
friend int add(Coordinate B);
public:
};
int add(Coordinate B)
{
std::cout << B.x << std::endl;
return B.x;
}

'B::operator A' uses undefined class 'A'

I have found the following example in one of my C++ courses. When I try to compile it I get the following error:
'B::operator A' uses undefined class 'A'
Why does it say that class A is undefined?
#include<iostream>
using namespace std;
class A;
class B
{
int x;
public: B(int i = 107) { x = i; }
operator A();
};
B::operator A() { return x; }
class A
{
int x;
public: A(int i = 6) { x = i; }
int get_x() { return x; }
};
int main()
{
B b;
A a = b;
cout << a.get_x();
system("Pause");
}
The compiler needs to know what A is here:
B::operator A() { return x; }
But you only have a forward declaration. You need to move the declaration of class A above B
You are only allowed to use pointers to or references of incomplete types which is what have when you forward declare a type
You need to declare A above B, so that the definition of A is visible to B.
#include<iostream>
using namespace std;
class A
{
int x;
public: A(int i = 6) { x = i; }
int get_x() { return x; }
};
class B
{
int x;
public: B(int i = 107) { x = i; }
operator A();
};
B::operator A() { return x; }
int main()
{
B b;
A a = b;
cout << a.get_x();
}
This should work.