Question with virtual functions - c++

I have two classes:
class x {
public:
virtual void hello() {
std::cout << "x" << std::endl;
}
};
class y : public x {
public:
void hello() {
std::cout << "y" << std::endl;
}
};
Can someone explain why the following two calls to hello() print different messages? Why don't they both print "y"? Is it because the first one is a copy while the second one actually points to the object in memory?
int main() {
y a;
x b = a;
b.hello(); // prints x
x* c = &a;
c->hello(); // prints y
return 0;
}

Yes, you are right
x b = a;
Invokes a copy constructor (b IS an 'x')
x& b = a;
Assigns a reference and will use the override (b is still actually a 'y')

Because x b = a; slices the object.
When this code executes, it creates a new x, not a y, which is a copy of the original y, a'.

x b = a copies a to b. Since b is type x, you end up with an object of type x. An object of type x will print x.
The only way you get y is when you are calling into an object of type y.

b.hello() prints "x" because b is an instance of class X. c->hello() prints "y" because c points to a, and a is an instance of class Y.
What might be confusing for you is that when you write x b = a;, you're creating a new object b and initializing it with a. When you write x* c = &a;, c is not a new object. You just introduced an alias to an existing object.

Related

When does reference casting slice objects?

Take a look at this piece of code:
#include <iostream>
class A{
public:
int x;
virtual void f(){std::cout << "A f\n";}
};
class B: public A
{
public:
int y;
void f() {std::cout << "B f\n";}
};
void fun( A & arg)
{
std::cout << "fun A called" << std::endl;
arg.f();
// arg.y = 222; - this gives error, compiler's work?
arg.x = 2223333;
}
void fun(B & arg){
std::cout << "fun B called" << std::endl;
arg.f();
}
int main()
{
B b;
b.y = 12;
b.x = 32;
fun(static_cast<A&>(b));
std::cout << b.x << " " << b.y << std::endl;
return 0;
}
What exactly happens when I reference cast b into A&? I'm guessing a reference to type A 'arg' is created in a funtion 'fun()' and now it's only compiler's work to differentiate types? Meaning no actual object was created and no slicing occurred and it's still the same object in memory, however compiler will treat it as type A? (meaning after function call I can safely use b as type B?)
I assumed that's true, because the vptr of the instance didn't change (arg of type A called B's virtual function override), but I'm not completely sure what's going on behind the scenes during reference casting.
Also, if I assign static_cast<A&>(b) to a new object of type A, I assume that's when the construction of a new object of type A and slicing occurres?
Yes, you seem to have got this. :-)
A B is also an A (by inheritance), so it can bind to either A& or B&. Nothing else happens, it is just a reference to the existing object.
The slicing happens if you assign a B object to an A object, like A a = b;, which will only copy the inherited A portion of b.

base class is a reference to another object

I just encountered a snippet of code which seems quite strange to me(see below as a minimal example), the derived::base is a reference to another object of type of base, can someone help me to answer the questions in the comments?
class base{
public:
int a;
int b;
};
class derived : public base{
public:
double c;
void run(const base & bs){
((base &) *this) = bs; // what does this line do?
// Is derived::base now a copy of bs?
// If yes, but why not write ((base) *this) = bs?
// if not, then derived::base is a reference to bs,
// then does it mean the memory of derived::base
// and members of derived are no longer contiguous?
std::cout << "a = " << a << std::endl;
}
};
PS
comments by #LightnessRacesinOrbit helped a lot to clear the questions, but I can only accept an answer post, the best is by #WhiZTiM
void run(const base & bs){
((base &) *this) = bs;
std::cout << "a = " << a << std::endl;
}
The above code can be broken down as:
void run(const base & bs){
base& base_of_this_instance = *this;
base_of_this_instance = bs;
std::cout << "a = " << a << std::endl;
}
The memory for an object of derived may be laid out as:
|| int a |x| int b |y| int c || // <- x and y represents some hypothetical padding
|| base |y| || // <- We can slice `derived` and retrieve only base
|| derived || // <- Memory consumed by derived
In your derived::run method, first, a reference to the base portion of derived is obtained, secondly that base is assigned to bs. This assignment will invoke the copy assignment operator of base. That means the base portion will now now hold a copy of whatever was in bs.
The result of
((base &) *this)
is references to base class
You can save it to a variable:
base& refToBase = ((base &) *this);
refToBase is a reference to the same object which is this
After that you have assignment
refToBase = bs;
It will assign bs's value to refToBase object
Like this:
int i = 10;
int p = 20;
int& refI = i;
int& refP = p;
refI = refP; // i == 20
p = 15; // p ==15 but i == 20
So after "strange code" from your example are executed we have the copies of bs.a and bs.b in derived::a and derived::b
the memory of derived::base and derived::c is still one batch

STL Container with iterator and inheritance

Here is a sample C++ question to find out the outcome.
#include <iostream>
#include <vector>
class A
{
public:
A(int n = 0) : m_n(n) { }
public:
virtual int f() const { return m_n; }
virtual ~A() { }
protected:
int m_n;
};
class B
: public A
{
public:
B(int n = 0) : A(n) { }
public:
virtual int f() const { return m_n + 1; }
};
int main()
{
const A a(1);
const B b(3);
const A *x[2] = { &a, &b };
typedef std::vector<A> V;
V y({ a, b });
V::const_iterator i = y.begin();
std::cout << x[0]->f() << x[1]->f()
<< i->f() << (i + 1)->f() << std::endl;
return 0;
}
The output I expected was "1 4 1 4" but the correct answer is "1 4 1 3".
From above,
x[0]->f()
i.e., x[0] is nothing but a pointer to an object of type A and calling f() returns 1.
x[1]->f()
i.e., x[1] is nothing but a pointer to an object of type A (base class pointer pointing to derived class object) and calls derived class f() that returns (3 + 1) = 4
I am not sure how this behaves when we add the objects a and b into a vector container and iterating them through const_iterator with inheritance
i->f()
I can understand this as i is just a pointer to the first element i.e., object a.
But what will happen here?
(i + 1)->f()
My understanding is that it points to the next element in the sequence i.e., object b and calling f() through derived class pointer should call its member function rather than base class one's?
The vector y contains two objects of type A. Not type B. When it is constructed, it makes copies of a and b, slicing b as it does so. So (i + 1)->f() calls A::f() on that copy of the A portion of b, giving 3.

C++ Assigning to an object variable?

I am learning c++ coming from a java background, I understand that in Java everything is implicitly a pointer (except primitive types) and so I've been using pointers when I want to use a variable that jumps between already allocated instances of classes.
What I would like to know is what happens when you do something like this:
class Thing1{
public:
Thing1() {n = 10;}
int n;
}
Thing1 A; // Creates an instance of Thing1
Thing1 B = A; // What happens here???
B.n = 5;
A.n = 16;
So two Thing1 objects get created on the stack right? Im confused about the behavior of assigning a variable containing an instance of a class to another instance of the class (assuming we dont overload the = operator). Any help?
First of all, your code is very wrong in line:
Thing1() = {n = 10};
It should be:
Thing1() {n = 10;} // notice deleted = and semicolon position
And you need to end class definition with semicolon.
Now, to answer your question: If you use = operator between same class objects and without overloading, you just basically set all member variables of B to values from A and those two objeccts are still independent from each other.
It's like:
int a = 5, b = 10;
b = a; // b = 10 and a = 10
b = 3 // b = 3 and a = 10
Consider this working piece of code:
#include <iostream>
using namespace std;
class Thing1
{
public:
Thing1() {n = 10;}
int n;
};
int main()
{
Thing1 A; // Creates an instance of Thing1
Thing1 B = A; // What happens here???
cout << B.n << endl << A.n << endl; // 10 10
B.n = 5;
A.n = 16;
cout << B.n << endl << A.n; // 5 16
return 0;
}
It prints out:
10
10
5
16
The meaning of the line:
Thing1 B = A; // What happens here???
B is an object of type Thing1, the members of object B are initialized with the current value of members of object A. You are not assigning the pointer of object A to object B, but just making another copy of A. This is done using copy constructor in C++.
Changing any member of B does not reflect in the corresponding member of class A.

confusing output

Below given program prints x = 10 y = 0
#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; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main()
{
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
but if we replace
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
with
Test &setX(int a) { x = a; return *this; }
Test &setY(int b) { y = b; return *this; }
output is x = 10 y = 20
Can anyone explain why this is happening?
When you return a plain object rather than a reference, you're returning a copy of the object on which you called the method. setY acts on that copy (which is a temporary), then the copy is destructed.
When you return a reference, all the calls operate on the same object, so you get the behavior you're looking for.
The first call to setX() returns a temporary copy of obj1 and the call to setY() modifies the temporary. Subsequent call to print() displays the state of obj1 and since in obj1 the y member variable was never modified it remains zero.
When you replace the return types with references, no temporary copy is made the both calls to setX() and setY() operate on obj.
Lets go back to basis about object oriented programming.
Lets use a metaphor - say a bus.
A bus has certain properties that can be changed - e.g. fuel.
So if you have a function (top up the fuel) you do not need a new bus that is exactly the same as the last one bit with a fuel tank that is full.
So going back to the original question.
Test setX(int a) { x = a; return *this; }
should read
void setX(int a) { x = a; }
etc.
You have the same object but the fuel may be topped up (or x in this case)
In the First case you are returning the object by value, Hence the copy of object will be created and returned.
So
obj1.setX(10) will return a copy of test and than .setY(20) will work on that copy thats why its effects are not on obj1 .
while in second case a reference to object is returned and hence .setY(20) will work on obj1 itself . Hence the output.
This pinter contain address of a object
In first case
in setx fun this pointer return x and and not free for return y value at simultaneously therfore he send copy of y not address of y.
In second case
This both function are different both have own this pointer
So they send address of both x and y