Why pointers to the same object have different values? [duplicate] - c++

This question already has answers here:
More than 1 address for derived class object?
(2 answers)
Closed 8 years ago.
I've this piece of code:
#include <iostream>
class A
{
public:
A() : m_i(0) { }
protected:
int m_i;
};
class B
{
public:
B() : m_d(0.0) { }
protected:
double m_d;
};
class C : public A, public B
{
public:
C() : m_c('a') { }
private:
char m_c;
};
int main()
{
C d;
A *b1 = &d;
B *b2 = &d;
std::cout << (long)b1 << std::endl <<(long)b2<< std::endl;
}
when compiled and run it produces the following output:
140734705182320
140734705182328
It is not completely clear why different pointers to the same address (&d) have different values.
thanks in advance.

The memory layout of a C object will be something like:
A base_object_1;
B base_object_2;
char m_c;
The two base objects have different addresses; A will (typically) have the same address as the full object, but B will (typically) not. Certainly they can't have the same address as each other, unless at least one is empty.
So converting a pointer to the full object into a pointer to one of the base objects must change the pointer value in order to point to the correct address.

Related

How to initialize an `const int` member in a base class when constructing child? [duplicate]

This question already has answers here:
How can I initialize base class member variables in derived class constructor?
(7 answers)
Closed 24 days ago.
#include <iostream>
class A {
public:
const int HP = 200;
A(){
std::cout << this->HP << std::endl;
}
};
class B : public A {
public:
B();
};
Constructing a B object will construct the A potion first.
I expect to reinitialize HP so that B() can print new HP.
Is this feasible for a base class const member ?
I need a member shared between base and child but to be constant in one instance of class, any suggestions?
You can add a constructor to A (and if needed also to B) that accepts the value for the const int member.
Then when you invoke A constructor from B constructor via the initializer list, you can pass this const value to the base.
Code example:
#include <iostream>
class A {
public:
const int HP = 200;
A() {
std::cout << this->HP << std::endl;
}
//----vvvvvv----vvvvvv--
A(int hp) : HP(hp) {
std::cout << this->HP << std::endl;
}
};
class B : public A {
public:
B() {};
//----vvvvvv----vvvvv--
B(int hp) : A(hp) {}
};
int main()
{
B b1;
B b2{ 99 };
}
Output:
200
99
Note: B can also be left as is (without an additional constructor), and pass the required const value to the base.

static_cast on objects c++ [duplicate]

This question already has answers here:
Why doesn't polymorphism work without pointers/references?
(6 answers)
What is object slicing?
(18 answers)
Closed 3 months ago.
I am trying to understand why static_cast works different when it is performed on object than when it is performed on a pointer to object.
class A
{
int myA;
public:
A() { myA = 11; };
virtual void Do() { printf("\n A class is executed "); }
};
class B : public A
{
int myB;
public:
B(){ myB = 22; }
void Do() { printf("\n B class is executed "); }
};
When the following cast is performed, A::Do() is executed. Why?
Why B's virtual table is neglected?
A t_a;
B t_b;
(static_cast<A>(t_b)).Do(); //output: A class is executed
But when it is done via pointer, B::Do() is executed.
A* pA = new B;
pA->Do();
(static_cast<A*>(pA))->Do(); //output: B class is executed
Can you give me a full explanation (including memory layout) to understand the difference.

Virtual Base Class and Diamond Problem in C++ [duplicate]

This question already has answers here:
How does virtual inheritance actually work?
(1 answer)
Internal mechanism of virtual inheritance
(1 answer)
How does virtual inheritance solve the "diamond" (multiple inheritance) ambiguity?
(5 answers)
How C++ virtual inheritance is implemented in compilers?
(5 answers)
Closed 11 months ago.
Consider the following code:-
#include<iostream>
using namespace std;
class A
{
public:
int a;
A()
{
a = 10;
cout<<"Address of a in A "<<&a<<endl;
}
};
class B : public virtual A {
public:
B()
{
cout<<"Address of a in B "<<&a<<endl;
}
};
class C : public virtual A {
public:
C()
{
cout<<"Address of a in C "<<&a<<endl;
}
};
class D : public B, public C {
public:
D()
{
cout<<"Address of a in D "<<&a<<endl;
}
};
int main()
{
A a;
B b;
C c;
D d;
return 0;
}
So, here when we create an object of D class, Constructors are called in this order A()->B()->C()->D().
Here A() is not called again before C() because we had made use of virtual keyword, which is preventing the constructor A() to be called again.
** Question: 1 But, I wanted to know what is happening in background in code when we are using the virtual keyword?
Question 2 And is variable a in class A and class B point to same memory location?
Question 3 And why this variable's memroy address differs in class C when A is not made virtual from the address of that variable in B?**

What would be a use case for dynamic_cast of siblings?

I'm reading Scott Meyers' More Effective C++ now. Edifying! Item 2 mentions that dynamic_cast can be used not only for downcasts but also for sibling casts. Could please anyone provide a (reasonably) non-contrived example of its usage for siblings? This silly test prints 0 as it should, but I can't imagine any application for such conversions.
#include <iostream>
using namespace std;
class B {
public:
virtual ~B() {}
};
class D1 : public B {};
class D2 : public B {};
int main() {
B* pb = new D1;
D2* pd2 = dynamic_cast<D2*>(pb);
cout << pd2 << endl;
}
The scenario you suggested doesn't match sidecast exactly, which is usually used for the casting between pointers/references of two classes, and the pointers/references are referring to an object of class which both derives from the two classes. Here's an example for it:
struct Readable {
virtual void read() = 0;
};
struct Writable {
virtual void write() = 0;
};
struct MyClass : Readable, Writable {
void read() { std::cout << "read"; }
void write() { std::cout << "write"; }
};
int main()
{
MyClass m;
Readable* pr = &m;
// sidecast to Writable* through Readable*, which points to an object of MyClass in fact
Writable* pw = dynamic_cast<Writable*>(pr);
if (pw) {
pw->write(); // safe to call
}
}
LIVE
It is called cross-cast, and it is used when a class inherits from two different classes (not the other way around, as shown in your question).
For example, given the following class-hierarchy:
A B
\ /
C
If you have an A pointer to a C object, then you can get a B pointer to that C object:
A* ap = new C;
B* bp = dynamic_cast<B*>(ap);

C++: Virtual methods [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 9 years ago.
I have the following piece of code (#includes and using namespace std omitted):
class A {
public:
void call(){callme();}
private:
virtual void callme() {cout << "I'm A" << endl;}
};
class B : public A {
private:
virtual void callme() {cout << "I'm B" << endl;}
};
class C : public B {
public:
virtual void callme(){ cout << "I'm C" << endl;}
};
int main(){
vector<A> stuff = {
A(), B(), C(),
};
stuff[0].call(); // output: I'm A
stuff[1].call(); // output: I'm A
stuff[2].call(); // output: I'm A
return 0;
}
As stated in the comments, the output of the above program is:
I'm A
I'm A
I'm A
However, I would like that C++ automatically recognizes the type with which the corresponding element was created. I.e. I would like that C++ outputs
I'm A
I'm B
I'm C
(That is, the compiler shall pick the proper subclass for me.)
Is this possible in this scenario (i.e. if all the elements come out of a vector)?
Member functions virtuality works only when you call them from pointer to the actual object, not from an object itself, because in your example objects were automatically statically upcasted to class A. Change your code to:
std::vector<std::unique_ptr<A>> stuff = {
std::unique_ptr<A>(new A()),
std::unique_ptr<A>(new B()),
std::unique_ptr<A>(new C()),
};
stuff[0]->call();
stuff[1]->call();
stuff[2]->call();
For C++ Polymorphism, you should use either pointer or reference. You could do like this
int main(){
vector<A*> stuff;
stuff.push_back(new A);
stuff.push_back(new B);
stuff.push_back(new C);
stuff[0]->call(); // output: I'm A
stuff[1]->call(); // output: I'm A
stuff[2]->call(); // output: I'm A
while (!stuff.empty()){
delete stuff.back();
stuff.pop_back();
}
return 0;
}
Reference: http://www.cplusplus.com/doc/tutorial/polymorphism/