V725. Dangerous cast of 'this' to 'void*' type in the 'Base' class, as it is followed by a subsequent cast to 'Class' type.
The analyzer has detected a dangerous casting of the this
pointer to the void*
type followed by a cast of void*
back to the class type. Casting this
to void*
is not an error, but in certain cases, casting void*
back to the class pointer is. Such conversions may lead to an invalid pointer.
Here is an example where this
is cast to void*
, followed by an invalid cast back to the class type:
class A
{
public:
A() : firstPart(1){}
void printFirstPart() { std::cout << firstPart << " "; }
private:
int firstPart;
};
class B
{
public:
B() : secondPart(2){}
void* GetAddr() const { return (void*)this; }
void printSecondPart() { std::cout << secondPart << " "; }
private:
int secondPart;
};
class C: public A, public B
{
public:
C() : A(), B(), thirdPart(3){}
void printThirdPart() { std::cout << thirdPart << " "; }
private:
int thirdPart;
};
void func()
{
C someObject;
someObject.printFirstPart();
someObject.printSecondPart();
someObject.printThirdPart();
void *pointerToObject = someObject.GetAddr();
....
auto pointerC = static_cast<C*>(pointerToObject);
pointerC->printFirstPart();
pointerC->printSecondPart();
pointerC->printThirdPart();
}
One might assume that the output would be as follows:
1 2 3 1 2 3
However, the following is printed:
1 2 3 2 3 -858993460
As a result, the output for all data after conversions is incorrect. The issue is that now pointerC
points to the memory block allocated for the B
object rather than to the beginning of the C
object.
This error may seem farfetched and unreal, but it is only obvious because the example above is short and simple. In real-life programs with complex class hierarchies, it may be far vaguer. The most confusing part is that the GetAddr()
function works when it's in the A
class, but fails when placed in the B
class.
To easily understand what caused the error, programmers need to know how class objects created using multiple inheritance are constructed and arranged in memory.
A schematic example is shown in the Figure 1.

Figure 1—The memory layout of a class object created through multiple inheritance.
The C
class object, obtained as a result of multiple inheritance, consists of the A
and B
class objects, as well as a part of the C
object.
The this
pointer points to the beginning of the memory block allocated for the object. The Figure 2 shows this
pointers for all the three objects.

Figure 2—The this
pointers and memory blocks.
Since the C
class object consists of three parts, its this
pointer points to the beginning of the entire continuous memory block rather than to an additional one. That is, this
pointers for the A
and C
classes match in this case.
The this
pointer for the B
class object points to the beginning of the memory block allocated for it, but its address differs from the starting address of the memory block allocated for the C
class object.
So, when calling the GetAddr()
method, a programmer gets the address of the B
object and then, after casting the resulting pointer back to the C*
type , they get an incorrect pointer.
In other words, if the GetAddr()
function were stored in the A
class, the program would work as expected, but when it is stored in B
, a developer gets an error.
To avoid such errors, programmers should consider whether they really need to cast this
to void*
. If the answer is yes, they need to carefully check the inheritance hierarchy and any casts of void*
back to the class pointer type.
References:
- Joost's Dev Blog. Hardcore C++: why "this" sometimes doesn't equal "this".
This diagnostic is classified as: