How are two different inherited pointer addresses equal? - c++

After reading C++: Comparing pointers of base and derived classes, I thought for sure this wouldn't work.
When I executed this, the printed addresses for c_as_b and &c were different, so why does this print "seems safe to compare pointers in same hierarchy"? What is being compared besides the printed addresses that could result in true?
Can you give a similar small example where the == results in false?
#include <iostream>
using namespace std;
struct A { std::string s; };
struct B { int i; };
struct C : A, B { double d; };
int main() {
C c;
B* c_as_b = &c;
A* c_as_a = &c;
cout << "c_as_a: " << c_as_a << endl
<< "c_as_b: " << c_as_b << endl
<< "&c: " << &c << endl;
cout << (c_as_b == &c ? "seems safe to compare pointers in same hierarchy" : "definately not safe") << endl;
return 0;
}
Sample output:
c_as_a: 0xbfb98f10
c_as_b: 0xbfb98f14
&c: 0xbfb98f10
seems safe to compare pointers in same hierarchy

The pointer equality comparison c_as_b == &c will do an implicit pointer conversion. From [expr.eq]:
If at least one of the operands is a pointer, pointer conversions (4.10), function pointer conversions (4.12),
and qualification conversions (4.4) are performed on both operands to bring them to their composite pointer
type (Clause 5).
Basically, &c will be converted to a B* so that the comparison can happen. At which point, it is exactly the same as c_as_b (since that's how you got that pointer to begin with), so they compare equal.

In this example, c is statically upcast to B, and then compared with c_as_b yielding true.

To answer the part of the question that nobody touched on: Can you give a similar small example where the == results in false?
Here is a similar example where the == results in false, using dynamic_cast<void*> makes the same comparison true, and commented out is a way that == results in a compile time error:
#include <iostream>
using namespace std;
struct A { virtual ~A() {} };
struct B : A { };
struct C : A { };
struct D : B, C { };
int main() {
D d;
C* c = &d;
B* b = &d;
A* a_through_b = b; // &d results in error: 'A' is an ambiguous base of 'D'
A* a_through_c = c;
cout << "&d: " << &d << endl
<< "c : " << c << endl
<< "b : " << b << endl
<< "a_through_b : " << a_through_b << endl
<< "a_through_c : " << a_through_c << endl;
cout << (a_through_b == a_through_c ? "a_through_b == a_through_c" : "a_through_b != a_through_c") << endl;
cout << (dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c) ? "dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c)" : "dynamic_cast<void*>(a_through_b) != dynamic_cast<void*>(a_through_c)") << endl;
//cout << (a_through_c == &d) << endl; // error: 'A' is an ambiguous base of 'D'
cout << (dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d) ? "dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d)" : "dynamic_cast<void*>(a_through_c) != dynamic_cast<void*>(&d)") << endl;
return 0;
}
Sample output:
&d: 0xbff6d558
c : 0xbff6d55c
b : 0xbff6d558
a_through_b : 0xbff6d558
a_through_c : 0xbff6d55c
a_through_b != a_through_c
dynamic_cast<void*>(a_through_b) == dynamic_cast<void*>(a_through_c)
dynamic_cast<void*>(a_through_c) == dynamic_cast<void*>(&d)

Related

C++ Pointer Comparison

How pointers are compared in C++?
The last line in the following code shows that values of b and c are different. However, b==c returns true.
#include <iostream>
struct A { int a; };
struct B { int b; };
struct C : A, B { };
int main() {
auto c = new C();
B* b = static_cast<B*>(c);
A* a = static_cast<A*>(c);
a->a = 1;
b->b = 2;
std::cout << c->a << c->b <<"\n";
std::cout << (a==c) << (b==c) << "\n";
std::cout << (long)a << "\n" << (long)b << "\n" << (long)c <<"\n";
}
A sample output that I received using GCC and Clang:
12
11
34073632
34073636
34073632
Don't cast pointers to long, cast them to intptr_t.
std::cout << (intptr_t)a << "\n" << (intptr_t)b << "\n" << (intptr_t)c <<"\n";
Anyhow, see this definition:
struct C : A, B { };
in memory that would look like:
{
A; [sizeof int]
B; [sizeof int]
}
Since A and B are both base classes of C, when you do this:
A* a = static_cast<A*>(c);
You get a pointer to the first 4 bytes of C. When you do this:
B* b = static_cast<B*>(c);
You get a pointer to the last 4 bytes of C, hence the difference. A pointer to type C will always implicitly cast the pointer this way.

Class casting in virtual functions c++

Hi I have the following piece of code -
class A{
public:
A(){
cout << "In A CTR" << endl;
}
virtual void buildTree() = 0;
void print(){
cout << "int A print This = " << this << endl;
}
};
class B{
public:
B(){
cout << "In B CTR" << endl;
}
virtual A* getBuilder() {
cout << " In B getBuilder , this = " << this << endl;
return NULL;
}
virtual void hell(){
cout << "In B hell This =" << this << endl;
}
void print(){
cout << "in B print This = " << this << endl;
}
B* add(B* child){
cout << "In B add , This = " << this <<endl;
}
};
class C : public A, public B{
public:
C(){
cout << "In C CTR" << endl;
}
A* getBuilder() {
cout << "In C getBuilder , this = " << this << endl;
return this;
}
void print(){
cout << "In C print This = " << this << endl;
}
};
class D : public C{
public:
D(){
cout <<"In D CTR" << endl;
}
void buildTree(){
cout << "buildTree in D , This = " << this << endl;
B *b = NULL;
add(b);
}
void print(){
cout << "In D print This = " << this << endl;
}
};
int main() {
B *root = new D();
root->getBuilder()->buildTree();
return 0;
}
I get the following output :
In C getBuilder , this = 0x7f9aa0500100
buildTree in D , this = 0x7f9aa0500100
In B add , this = 0x7f9aa0500108
I am unable to figure out , why the add() in class B is called . Here is my understanding . Please correct me.
root is a pointer of type B and points to D .
So, when root->getBuilder() is called , it calls the virtual function in class C , which returns a pointer of type A* .
So, now root->getBuilder() returns a pointer of type A pointing to D.
Hence root->getBuilder()->buildTree() is able to call buildTree in D .
But in the buildTree in class D , we are calling add which is defined in class B.
How are we able to call this , as the pointer type is A and should not know nothing about B, functions .
Any help is appreciated.
Thanks
This seems to be the question:
But in the buildTree in class D , we are calling add which is defined
in class B. How are we able to call this , as the pointer type is A
and should not know nothing about B, functions.
Calling buildTree on a pointer type of A* where buildTree is marked as virtual is going to call buildTree on a D* given root is of type D. So add is available to D because D can access the public and protected methods of is superclasses.
The original code example is unnecessarily complicated. The same principle can be examined via the following code:
A *root = new D();
root->buildTree();
What you have is basically this (very simplified):
struct B
{
B* add(B*)
{
std::cout << "B::add\n";
}
};
struct C : B
{
// Nothing relevant
};
struct D : C
{
void buildTree()
{
add(NULL);
}
};
int main()
{
D root;
root.buildTree();
}
The class D is a C. The class C is a B. That means D is a B as well. Therefore D has the member function add.
The pointers and indirection are red herrings in the case of how you can call add from a D member function.
I think I see the problem now, and it's about the interface the classes present to the world.
Again with a basic and simplified example:
struct A
{
void funA();
}
struct B
{
// Nothing relevant
};
struct C : A, B
{
// Nothing relevant
};
Then by doing
B* p = new C;
is valid. But even though the pointer p is pointing to an object of C (which is also an A) it does not have the interface of A (or C for that matter), only of B.
If you want to use the functions in A or C you have to use down-casting to cast it to the correct type:
static_cast<D*>(p)->funA(); // Cast to the type `p` *really* is

Initialize a object with a derived class constructor

Consider the following C++ code:
#include <iostream>
using std::cout;
class A
{
public:
int a;
A():a(0)
{
cout << "A constructor\n";
}
virtual void f()
{
cout << "f inside A\n";
}
};
class C : public A
{
public:
int c;
virtual void f()
{
cout << "f inside C\n";
}
C():c(0)
{
cout << "C constructor\n";
}
};
int main()
{
A varA = C();
cout << "Size of C class: " << sizeof(C) << "\n";
cout << "Size of varA object: " << sizeof(varA) << "\n";
C* varC = static_cast<C*>(&varA);
varC->f();
cout << "varC->a is " << varC->a << "\n";
cout << "varC->c is " << varC->c << "\n";
}
The output of this program is:
A constructor
C constructor
Size of C class: 16
Size of varA object: 8
f inside A
varC->a is 0
varC->c is 1726166356
I initialize the varA object with the constructor of class C. Constructors of A and C class are called, but the varA is a simply a A object. I cast the address of varA to C* type and I try to call its f() function, but it prints the f() function of class A, so I deduce that it is use the early binding mechanism to call it.
I think if I call the constructor of derived class, like this case, I obtain the same object if I had called the base constructor.
I think the only difference is the other constructors are called. Is my supposition right or there are any other differences?
Classic example of slicing. A varA = C(); leaves you with object of static and dynamic type of A. As a result, C* varC = static_cast<C*>(&varA); exhibits undefined behavior.
You can store a complete derived class in a base-class pointer, however:
int main() {
A* varA = new C();
C* varC = static_cast<C*>(varA);
varC->f();
cout << "varC->a is " << varC->a << endl;
cout << "varC->b is " << varC->b << endl;
cout << "varC->c is " << varC->c << endl;
} // oops, forgot to delete varA/varC, memory leak!

pointer equality in multiple inheritance

I wonder how pointers are compared when it comes to multiple inheritance. It seems that in some circumstance, they are equal although the address is obviously different. See the following code:
class A {
int m_i;
};
class B {
double m_d;
};
class C: public A, public B {
char m_c;
};
int main() {
C c;
A *pa = &c;
B *pb = &c;
std::cout << "Address of c is: " << &c << std::endl;
std::cout << "A type pointer to c is: " << pa << std::endl;
std::cout << "B type pointer to c is: " << pb << std::endl;
std::cout << "if pa == &c: " << (pa == &c) << std::endl;
std::cout << "if pb == &c: " << (pb == &c) << std::endl;
return 0;
}
The output is:
Address of c is: 00F6F870
A type pointer to c is: 00F6F870
B type pointer to c is: 00F6F878
if pa == &c: 1
if pb == &c: 1
There is no wonder pb is different from &c. The weird thing is (pb == &c) delivers 1. I am now confused how (pb == &c) is actually evaluated.
You can only compare values that have the same type. Note, I'm ignoring the case of an overloaded operator== for the purpose of this answer.
Here, you're comparing two pointers to different classes. At this point, the compiler tries to figure out if it's possible to convert one of the pointers to the type of the other pointer.
A pointer to a subclass can be automatically converted to a pointer to its superclass. And this is what the compiler does. The end result is the same actual pointer value, and they compare equal.
This line:
std::cout << "if pb == &c: " << (pb == &c) << std::endl;
in order to compare &c with pb it has to perform a conversion so that the types of the two values match. We already know that (B*)&c results in the value that is in pb, so what actually happens here is quite simply
std::cout << "if pb == &c: " << (pb == (B*)&c) << std::endl;
which results in comparing equal values.
class X {
char m_x;
};
class A {
int m_i;
};
class B {
double m_d;
};
class C: public X, public A, public B {
char m_c;
};
int main() {
C c;
A *pa = &c;
B *pb = &c;
void *va = pa;
void *vb = pb;
std::cout << "Address of c is: " << &c << std::endl;
std::cout << "A type pointer to c is: " << pa << std::endl;
std::cout << "B type pointer to c is: " << pb << std::endl;
std::cout << "void type pointer equal to pA is: " << va << std::endl;
std::cout << "void type pointer equal to pB is: " << vb << std::endl;
std::cout << "if pa == &c: " << (pa == &c) << std::endl;
std::cout << "if pb == &c: " << (pb == &c) << std::endl;
std::cout << "if va == &c: " << (&c == va) << std::endl;
std::cout << "if vb == &c: " << (&c == vb) << std::endl;
return 0;
}
yields the following result:
Address of c is: 0x75270a47f5f0
A type pointer to c is: 0x75270a47f5f4
B type pointer to c is: 0x75270a47f5f8
void type pointer equal to pA is: 0x75270a47f5f4
void type pointer equal to pB is: 0x75270a47f5f8
if pa == &c: 1
if pb == &c: 1
if va == &c: 0
if vb == &c: 0
The compiler converts the &c address by casting it to the same type as the pointer you compared it to. To make the point clear I displaced Class A using another class, when I then copy the addresses to void* pointers it becomes clear that the actual 'value' stored is not equal to the 'value' stored in &c.

C++ - Copy constructor with pointers as the data field

I have the following code :-
#include <iostream>
using namespace std;
class A {
int *val;
public:
A() { val = new int; *val = 0; }
int get() { return ++(*val); }
};
int main() {
A a,b = a;
A c,d = c;
cout << a.get() << b.get() ;
cout << endl ;
cout << c.get() << endl ;//
cout << d.get() << endl;
return 0;
}
It produces the output as :-
21
1
2
The behavior in case of c.get and d.get is easy to understand.
Both c and d share the same pointer val and a and b share the same pointer val.
So c.get() should return 1 and d.get() should return 2.
But I was expecting similar behavior in a.get() and b.get(). (maybe I have not understood cout properly)
I am unable to understand how a.get() is producing 2.
Can you explain why I am getting such an output. According to me the output should have been :-
12
1
2
cout << a.get() << b.get() ;
gets executed as:
cout.operator<<(a.get()).operator<<(b.get());
In this expression, whether a.get() gets called first or b.get() gets called first is not specified by the language. It is platform dependent.
You can separate them into two statements to make sure they get executed in an expected order.
cout << a.get();
cout << b.get();