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";
}
Related
#include <iostream>
using namespace std;
class myPair {
private:
int x, y;
public:
myPair(int x = 3, int y = 2) {};
friend void out(string a) {};
};
void out(string a) {
myPair p;
cout << a << "x equals " << p.x << "and " << a << "y equals " << p.y;
};
int main() {
myPair A(5, 3);
A.out("A : ");
}
this code is supposed to print out info about myPair class object but for some reason compiler tells me that there is not any member with the name of out() in myPair
The behaviour of your code is undefined. This is because you don't set the member variables in myPair and then subsequently read their values.
Rather than your out function, it's idiomatic C++ to define the << operator for ostream and your class. In that way you can use it directly in a cout statement. Here are the changes, including the fix to your constructor:
#include <iostream>
class myPair {
private:
int x;
int y;
public:
myPair(int x = 3, int y = 2) : x(x), y(y) /*there is no ambiguity here bizarrely*/
{
};
friend std::ostream& operator<<(std::ostream& os, const myPair& p);
};
std::ostream& operator<<(std::ostream& os, const myPair& p){
os << "x equals " << p.x << " and y equals " << p.y;
return os;
}
int main() {
myPair A(5, 3);
std::cout << "A: " << A;
}
You declare a function friend to the class so that this function can access the private data members of the class. And remember you cannot call friend function like A.out as it just an external function with special privileges and does not have this pointer. So it cannot be called that way.
And further, when you put {} in the front of the function signatures it becomes a definition. So You have to obey ODR(One Definition Rule). While declaring the friend function you cannot put {} otherwise you will get an error.
One more thing your constructor is not constructing the object properly, it is just taking parameters and doing nothing.
To let your friend do something to an object is to pass the object in the friend function.
You can see below the correct version of your code:
#include <iostream>
using namespace std;
class myPair {
private:
int x, y;
public:
myPair(int _x = 3, int _y = 2): x(_x), y(_y) {};
friend void out(const string& a, myPair& p);
};
void out(const string& a, myPair& p) {
//myPair p;
cout << a << "x equals " << p.x << "and " << a << "y equals " << p.y;
};
int main() {
myPair A(5, 3);
out("A : ", A);
}
This is not a method, so You need to pass your object into out("", myPair). It works as expected.
You are declaring out as a friend function not a member. So your code should look like,
#include <iostream>
using namespace std;
class myPair {
private:
int x, y;
public:
myPair(int x = 3, int y = 2) : x(x), y(y){};
void out(string);
};
void myPair::out(string a) {
cout << a << "x equals " << this->x << "and " << a << "y equals " << this->y;
};
int main() {
myPair A(5, 3);
A.out("A : ");
}
If you want friend functions you can do,
#include <iostream>
using namespace std;
class myPair {
private:
int x, y;
public:
myPair(int x = 3, int y = 2) : x(x), y(y) {};
friend void out(myPair p, string a);
};
void out(myPair p, string a) {
cout << a << "x equals " << p.x << "and " << a << "y equals " << p.y;
};
int main() {
myPair A(5, 3);
out(A, "A : ");
}
I want to make an operator= and copy constructor, to be called in the inherited class.
For normal objects, it works fine, but when I'm trying to call, for example, operator= with a pointer, it is just copying the object address.
So my question is, how can I call those methods with pointers?
#include <iostream>
// base class
class a {
public:
//constructors
a(): x(0), y(1), z(0){ std::cout << "no parameter constructor A\n"; }
a(int a, int b, int c) :x(a), y(b), z(c){ std::cout << "parameter constructor A\n"; }
a(const a& ob):x(ob.x), y(ob.y), z(ob.z)
{
std::cout << "copy constructor A\n";
}
//operator
a& operator=(const a& obj)
{
if (this != &obj)
{
x = obj.x;
y = obj.y;
z = obj.z;
}
std::cout << "operator = A\n";
return *this;
}
protected:
int x, y, z;
};
//child class
class b : public a
{
public:
//constructors
b() : p(0){ std::cout << "no parameter constructor B\n"; }
b(int X, int Y, int Z, int B) : a(X, Y, Z), p(B) { std::cout << "parameter constructor B\n"; }
b(const b& obj) :p(obj.p), a(obj)
{
std::cout << "copy constructor B\n";
}
//operator =
b& operator=(const b &obj)
{
if (this != &obj)
{
p = obj.p;
&a::operator=(obj);
}
std::cout << "operator = B\n";
return *this;
}
private:
int p;
};
int main()
{
b obj0(4, 8, 16, 32);
b obj1(obj0); // copy constructor
b obj2;
obj2 = obj1; // operator =
std::cout << std::endl << std::endl;
std::cout << "for pointers:\n\n";
a* obj3 = new b(4, 8, 16, 32);
a* obj4(obj3);
obj4 = obj3;
return 0;
}
One of the purposes of using pointers (or references) is to avoid needing to create a copy of the object. Passing a pointer to the object allows the receiver to refer to and manipulate on the original object.
If you wish the pointer to receive a new object, then you would use new.
When dealing with polymorphism as in your example, you would probably need a virtual method that creates a proper clone (sometimes called a deep copy).
class a {
//...
virtual a * clone () const = 0;
};
class b : public a {
//...
b * clone () const {
return new b(*this);
}
};
//...
a *obj4 = obj3->clone();
//...
We leverage that b * is a covariant return type for a *, so that b::clone() can return a b *, but a::clone() can use the b::clone() as an override and still return an a *.
I have these 2 specific classes:
class foo{
private:
int a;
int b;
public:
foo(int x, int y)
:a(x), b(y)
{
cout << "I just created a foo! << endl;
}
~foo()
{
cout << "A foo was just destroyed!" << endl;
}
void set_a(int a_num)
{
a = a_num;
}
void set_b(int b_num)
{
b = b_num;
}
class bar{
private:
int T;
int S;
foo f;
public:
bar(int x, int y, foo n=(0,0) <--
:T(x), S(y), f(n)
{
cout << "I just created a f!" << endl;
foo.set_a(T); <--
foo.set_b(S); <--
}
~bar(){
cout << "A bar was destroyed!" << endl;
}
When a bar is created, i want the given values T and S to be assigned immediately to the foo object-member.At the marked lines i tried to overwrite these values but none of these seems to work and i get the error: "default argument for parameter of type foo has type 'int'".How can i get this to work?
You can use:
bar(int x, int y, foo n=foo(0,0)) : ... { ... }
If you are able to use a C++11 compiler, you can also use:
bar(int x, int y, foo n=foo{0,0}) : ... { ... }
and
bar(int x, int y, foo n={0,0}) : ... { ... }
Instead of:
foo.set_a(T);
foo.set_b(S);
you need to use:
f.set_a(T);
f.set_b(S);
since you need to call set_a and set_b on the member variable f.
A better alternative is to initialize f using:
bar(int x, int y} : T(x), S(y), f(x, y) {}
and leave the body of the constructor empty.
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;
}
Here, values of x and y is being tried to set through base class constructor.
But, the code is unable to do so.
#include <iostream>
class Point2d {
public:
double x;
double y;
Point2d() : x(0), y(0) {
}
Point2d(double x, double y) : x(x), y(y) {
}
void Show() {
std::cout << "(" << x << "," << y << ")\n";
}
};
class Vector2d : public Point2d {
public:
Vector2d():Point2d(){
}
Vector2d(double x, double y) : Point2d(x,y) {
}
Vector2d(Vector2d const& vec) : Point2d(vec){
}
void Set(double x, double y) {
Point2d::Point2d(x, y);
}
};
int main() {
Vector2d v;
v.Set(20, -39);
v.Show(); // prints '(0,0)' instead of '(20,-39)'
}
My target is to reuse base class constructor, and, overloaded assignment operators as much as possible.
I'm afraid your code won't even compile at
void Set(double x, double y)
{
Point2d::Point2d(x, y);
}
A constructor of a base class should be called at the beginning of the member initializer lists of a subclass constructor, not in a member function.
What you need is probably
class Point2d {
public:
double x;
double y;
Point2d() : x(0), y(0) {
}
Point2d(double x, double y) : x(x), y(y) {
}
void Show() {
std::cout << "(" << x << "," << y << ")\n";
}
Point2d& operator=(Point2d const& rhs)
{
this->x = rhs.x;
this->y = rhs.y;
}
};
class Vector2d : public Point2d {
public:
Vector2d():Point2d(){
}
Vector2d(double x, double y) : Point2d(x,y) {
}
Vector2d(Vector2d const& vec) : Point2d(vec){
}
/* also need to be overloaded in the subclass */
Vector2d& operator=(Vector2d const& rhs)
{
Point2d::operator=(rhs);
return *this;
}
void Set(double x, double y) {
*this = Vector2d(x, y);
}
};
int main() {
Vector2d v;
v.Set(20, -39);
v.Show();
}
Well, you're trying to construct the base class in the setter function, but the base class will already be constructed when the derived class is constructed. I would just set the x and y values of the base class in the setter.