For the following code
class A
{
public:
~A()
{
std::cout << "a" << std::endl;
}
};
class B : public A {
public:
virtual ~B()
{
std::cout << "b" << std::endl;
}
};
int main()
{
B* b = new B();
A* a = b;
if (a == b)
{
}
delete a;
}
Question is , will “a” equals to “b” ? Why and How this happened? And what a pointer really means? Not just an address and the length of the memory block?
will “a” equals to “b” ?
Yes
Why and How this happened?
To perform the comparison of the two pointers the compiler will perform a conversion to a common type. In this case, as A
is a base of B
, the conversion is to A*
, yielding code equivalent to:
A* __tmp = b;
if ( a == __tmp ) ...
And what a pointer really means? Not just an address and the length of the memory block?
A pointer is a variable the holds the address of an object (no size information stored in the pointer). But the pointer has a type, and the compiler will interpret the memory location that the pointer refers to be an object of that type. That extra information that is stored outside of the pointer is what allows the compiler to perform the conversion.
The a
variable will point at the A
class portion of the allocated b
object. A pointer is just a memory address, nothing more. What is important is what kind of data the pointer is pointing at in memory.
Let's split the answer in three parts
Pointers
A pointer is a variable which holds the memory address of another variable. The type of the pointed variable is important and will be checked by the compiler. One can force the pointer mechanic by using pointers to void (should be avoided in C++, unless you really know what you are doing).
Accessing derived class objects using base class pointers
An object, i.e. a variable, of a derived class (b
in your code) can be referred to using a pointer to its parent type (A
in your code). This will allow you to access the members of A that are present in B
. As already stated by Richard J. Ross, using a pointer to the base class will yield the same address as using the derived class pointer (unless multiple inheritance is involved).
Virtual functions
Virtual methods allow you to call an overloaded method of the derived object using a base class pointer. This is especially useful for destructors because one can rest assured that objects will be properly destroyed even when using a base class pointer (assuming the destructor is well written).
Still, your code is conceptually wrong. Because the destructor of A
is not virtual, the destructor of the B
part of b
will not be called, hence there might be memory leaks and similar problems.
As David already mentioned, simple comparison of two pointers a == b
will give you True because the compiler will cast both of them to the common type. But, if you were to modify this to (void*)a == (void*)b
, result may be false. This is because classes A and B have different memory layouts due to B having a virtual function table and A - not.
MSVC compiler puts virtual function pointer on the "top" of the class, before the first data member, but nothing stops other compilers from placing it on the "bottom".
You may also try making class A destructor virtual.
I found some explain on inside c++ object model, this is just like multiple inheritance, the vptr locates at the beginning of the object. when the base class having no virtual and child class having a virtual, the assign of pointer will be adjusted by the compiler by step over the vptr,
The example is a comparison between two pointers. As they are pointing to the same location, a will be equal to b.
For the following code
class A
{
public:
~A()
{
std::cout << "a" << std::endl;
}
};
class B : public A {
public:
virtual ~B()
{
std::cout << "b" << std::endl;
}
};
int main()
{
B* b = new B();
A* a = b;
if (a == b)
{
}
delete a;
}
Question is , will “a” equals to “b” ? Why and How this happened? And what a pointer really means? Not just an address and the length of the memory block?
will “a” equals to “b” ?
Yes
Why and How this happened?
To perform the comparison of the two pointers the compiler will perform a conversion to a common type. In this case, as A
is a base of B
, the conversion is to A*
, yielding code equivalent to:
A* __tmp = b;
if ( a == __tmp ) ...
And what a pointer really means? Not just an address and the length of the memory block?
A pointer is a variable the holds the address of an object (no size information stored in the pointer). But the pointer has a type, and the compiler will interpret the memory location that the pointer refers to be an object of that type. That extra information that is stored outside of the pointer is what allows the compiler to perform the conversion.
The a
variable will point at the A
class portion of the allocated b
object. A pointer is just a memory address, nothing more. What is important is what kind of data the pointer is pointing at in memory.
Let's split the answer in three parts
Pointers
A pointer is a variable which holds the memory address of another variable. The type of the pointed variable is important and will be checked by the compiler. One can force the pointer mechanic by using pointers to void (should be avoided in C++, unless you really know what you are doing).
Accessing derived class objects using base class pointers
An object, i.e. a variable, of a derived class (b
in your code) can be referred to using a pointer to its parent type (A
in your code). This will allow you to access the members of A that are present in B
. As already stated by Richard J. Ross, using a pointer to the base class will yield the same address as using the derived class pointer (unless multiple inheritance is involved).
Virtual functions
Virtual methods allow you to call an overloaded method of the derived object using a base class pointer. This is especially useful for destructors because one can rest assured that objects will be properly destroyed even when using a base class pointer (assuming the destructor is well written).
Still, your code is conceptually wrong. Because the destructor of A
is not virtual, the destructor of the B
part of b
will not be called, hence there might be memory leaks and similar problems.
As David already mentioned, simple comparison of two pointers a == b
will give you True because the compiler will cast both of them to the common type. But, if you were to modify this to (void*)a == (void*)b
, result may be false. This is because classes A and B have different memory layouts due to B having a virtual function table and A - not.
MSVC compiler puts virtual function pointer on the "top" of the class, before the first data member, but nothing stops other compilers from placing it on the "bottom".
You may also try making class A destructor virtual.
I found some explain on inside c++ object model, this is just like multiple inheritance, the vptr locates at the beginning of the object. when the base class having no virtual and child class having a virtual, the assign of pointer will be adjusted by the compiler by step over the vptr,
The example is a comparison between two pointers. As they are pointing to the same location, a will be equal to b.
0 commentaires:
Enregistrer un commentaire