This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 15.1.1 - An object’s dynamic type shall not be used from within its constructor or destructor
[class.abstract] Undefined 6
[class.cdtor] Undefined 3, 4, 5
Category: Required
Analysis: Undecidable,System
Amplification
For the purposes of this rule, the initialization of a non-static data member (including via a default member initializer) is considered
as being part of the constructor.
The dynamic type of an object is used when:
- A virtual call is made to a virtual function;
-
typeid is applied to an object with polymorphic class type;
- Using
dynamic_cast.
Rationale
During construction and destruction of an object, its type may be different from the type of the fully constructed object. The result of using an
object’s dynamic type in a constructor or destructor may not be consistent with developer expectations.
This rule also prohibits a virtual call being made to a pure virtual function from within a constructor or destructor. Such calls result in
undefined behaviour.
Additionally, using the dynamic type of the current object through a pointer or reference to a child class of the current class results in
undefined behaviour, and is therefore also prohibited by this rule.
Example
class B1
{
public:
B1()
{
typeid( *this ); // Compliant - B1 not polymorphic
}
};
class B2
{
public:
virtual ~B2();
virtual void foo();
virtual void goo() = 0;
void bar()
{
foo();
typeid( *this );
}
B2()
{
typeid( *this ); // Non-compliant
typeid( B2 ); // Compliant - current object type not used
B2::foo(); // Compliant - not a virtual call
foo(); // Non-compliant
goo(); // Non-compliant - undefined behaviour
dynamic_cast< B2 * >( this ); // Non-compliant
bar(); // Non-compliant - indirect call to foo and
// use of typeid on current object
}
};
The following example is non-compliant and has undefined behaviour when a virtual call is made on the object under construction through an indirect
pointer.
class B4;
class B3
{
public:
explicit B3( B4 * b );
virtual ~B3();
virtual void foo();
};
class B4 : public B3
{
public:
B4() : B3( this ) { }
};
B3::B3( B4 * b )
{
foo(); // Non-compliant - calls B3::foo
this->foo(); // Non-compliant - calls B3::foo
b->foo(); // Non-compliant - undefined behaviour
}
Copyright The MISRA Consortium Limited © 2023