Daily formed vs. static_cast vs. dynamic_cast

Daily formed vs. static_cast vs. dynamic_cast

I've been penning C and C++ codification for about 20 years, however location's 1 facet of these languages that I've ne\'er truly understood. I've evidently utilized daily casts i.e.

MyClass *m = (MyClass *)ptr;

each complete the spot, however location look to beryllium 2 another varieties of casts, and I don't cognize the quality. What's the quality betwixt the pursuing traces of codification?

MyClass *m = (MyClass *)ptr;MyClass *m = static_cast<MyClass *>(ptr);MyClass *m = dynamic_cast<MyClass *>(ptr);

static_cast

static_cast is utilized for instances wherever you fundamentally privation to reverse an implicit conversion, with a fewer restrictions and additions. static_cast performs nary runtime checks. This ought to beryllium utilized if you cognize that you mention to an entity of a circumstantial kind, and frankincense a cheque would beryllium pointless. Illustration:

void func(void *data) { // Conversion from MyClass* -> void* is implicit MyClass *c = static_cast<MyClass*>(data); ...}int main() { MyClass c; start_thread(&func, &c) // func(&c) will be called .join();}

Successful this illustration, you cognize that you handed a MyClass entity, and frankincense location isn't immoderate demand for a runtime cheque to guarantee this.

dynamic_cast

dynamic_cast is utile once you don't cognize what the dynamic kind of the entity is. It returns a null pointer if the entity referred to doesn't incorporate the kind casted to arsenic a basal people (once you formed to a mention, a bad_cast objection is thrown successful that lawsuit).

if (JumpStm *j = dynamic_cast<JumpStm*>(&stm)) { ...} else if (ExprStm *e = dynamic_cast<ExprStm*>(&stm)) { ...}

You tin not usage dynamic_cast for downcast (casting to a derived people) if the statement kind is not polymorphic. For illustration, the pursuing codification is not legitimate, due to the fact that Base doesn't incorporate immoderate digital relation:

struct Base { };struct Derived : Base { };int main() { Derived d; Base *b = &d; dynamic_cast<Derived*>(b); // Invalid}

An "ahead-formed" (formed to the basal people) is ever legitimate with some static_cast and dynamic_cast, and besides with out immoderate formed, arsenic an "ahead-formed" is an implicit conversion (assuming the basal people is accessible, i.e. it's a public inheritance).

Daily Formed

These casts are besides referred to as C-kind formed. A C-kind formed is fundamentally an identical to making an attempt retired a scope of sequences of C++ casts, and taking the archetypal C++ formed that plant, with out always contemplating dynamic_cast. Unnecessary to opportunity, this is overmuch much almighty arsenic it combines each of const_cast, static_cast and reinterpret_cast, however it's besides unsafe, due to the fact that it does not usage dynamic_cast.

Successful summation, C-kind casts not lone let you to bash this, however they besides let you to safely formed to a backstage basal-people, piece the "equal" static_cast series would springiness you a compile-clip mistake for that.

Any group like C-kind casts due to the fact that of their brevity. I usage them for numeric casts lone, and usage the due C++ casts once person outlined sorts are active, arsenic they supply stricter checking.


Static formed

The static formed performs conversions betwixt suitable varieties. It is akin to the C-kind formed, however is much restrictive. For illustration, the C-kind formed would let an integer pointer to component to a char.
char c = 10; // 1 byteint *p = (int*)&c; // 4 bytes

Since this outcomes successful a Four-byte pointer pointing to 1 byte of allotted representation, penning to this pointer volition both origin a tally-clip mistake oregon volition overwrite any adjoining representation.

*p = 5; // run-time error: stack corruption

Successful opposition to the C-kind formed, the static formed volition let the compiler to cheque that the pointer and pointee information varieties are suitable, which permits the programmer to drawback this incorrect pointer duty throughout compilation.

int *q = static_cast<int*>(&c); // compile-time error

Reinterpret formed

To unit the pointer conversion, successful the aforesaid manner arsenic the C-kind formed does successful the inheritance, the reinterpret formed would beryllium utilized alternatively.

int *r = reinterpret_cast<int*>(&c); // forced conversion

This formed handles conversions betwixt definite unrelated varieties, specified arsenic from 1 pointer kind to different incompatible pointer kind. It volition merely execute a binary transcript of the information with out altering the underlying spot form. Line that the consequence of specified a debased-flat cognition is scheme-circumstantial and so not transportable. It ought to beryllium utilized with warning if it can't beryllium prevented altogether.

Dynamic formed

This 1 is lone utilized to person entity pointers and entity references into another pointer oregon mention varieties successful the inheritance hierarchy. It is the lone formed that makes certain that the entity pointed to tin beryllium transformed, by performing a tally-clip cheque that the pointer refers to a absolute entity of the vacation spot kind. For this tally-clip cheque to beryllium imaginable the entity essential beryllium polymorphic. That is, the people essential specify oregon inherit astatine slightest 1 digital relation. This is due to the fact that the compiler volition lone make the wanted tally-clip kind accusation for specified objects.

Dynamic formed examples

Successful the illustration beneath, a MyChild pointer is transformed into a MyBase pointer utilizing a dynamic formed. This derived-to-basal conversion succeeds, due to the fact that the Kid entity contains a absolute Basal entity.

class MyBase { public: virtual void test() {}};class MyChild : public MyBase {};int main(){ MyChild *child = new MyChild(); MyBase *base = dynamic_cast<MyBase*>(child); // ok}

The adjacent illustration makes an attempt to person a MyBase pointer to a MyChild pointer. Since the Basal entity does not incorporate a absolute Kid entity this pointer conversion volition neglect. To bespeak this, the dynamic formed returns a null pointer. This offers a handy manner to cheque whether or not oregon not a conversion has succeeded throughout tally-clip.

MyBase *base = new MyBase();MyChild *child = dynamic_cast<MyChild*>(base); if (child == 0) std::cout << "Null pointer returned";

If a mention is transformed alternatively of a pointer, the dynamic formed volition past neglect by throwing a bad_cast objection. This wants to beryllium dealt with utilizing a try-catch message.

#include <exception>// … try{ MyChild &child = dynamic_cast<MyChild&>(*base);}catch(std::bad_cast &e) { std::cout << e.what(); // bad dynamic_cast}

Dynamic oregon static formed

The vantage of utilizing a dynamic formed is that it permits the programmer to cheque whether or not oregon not a conversion has succeeded throughout tally-clip. The drawback is that location is a show overhead related with doing this cheque. For this ground utilizing a static formed would person been preferable successful the archetypal illustration, due to the fact that a derived-to-basal conversion volition ne\'er neglect.

MyBase *base = static_cast<MyBase*>(child); // ok

Nevertheless, successful the 2nd illustration the conversion whitethorn pb to tally-clip mistake. The mistake volition hap if the MyBase entity accommodates a MyBase case however not if it accommodates a MyChild case. Successful any conditions this whitethorn not beryllium recognized till tally-clip. Once this is the lawsuit dynamic formed is a amended prime than static formed.

// Succeeds for a MyChild objectMyChild *child = dynamic_cast<MyChild*>(base);

If the basal-to-derived conversion had been carried out utilizing a static formed alternatively of a dynamic formed the conversion would not person failed. It would person returned a pointer that referred to an incomplete entity. Dereferencing specified a pointer tin pb to tally-clip errors.

// Allowed, but invalidMyChild *child = static_cast<MyChild*>(base); // Incomplete MyChild object dereferenced(*child);

Const formed

This 1 is chiefly utilized to adhd oregon distance the const modifier of a adaptable.

const int myConst = 5;int *nonConst = const_cast<int*>(&myConst); // removes const

Though const formed permits the worth of a changeless to beryllium modified, doing truthful is inactive invalid codification that whitethorn origin a tally-clip mistake. This might happen for illustration if the changeless was situated successful a conception of publication-lone representation.

*nonConst = 10; // potential run-time error

const formed is alternatively utilized chiefly once location is a relation that takes a non-changeless pointer statement, equal although it does not modify the pointee.

void print(int *p) { std::cout << *p;}

The relation tin past beryllium handed a changeless adaptable by utilizing a const formed.

print(&myConst); // error: cannot convert // const int* to int* print(nonConst); // allowed

Origin and Much Explanations


Casting successful C++ is a cardinal conception that permits you to dainty an entity of 1 kind arsenic if it had been an entity of different kind. Piece C++ presents respective casting operators, knowing the nuances betwixt them is important for penning harmless and businesslike codification. This weblog station delves into the distinctions betwixt dynamic_cast, static_cast, and the conception of 'regular fashioned' sorts, highlighting their usage instances, advantages, and possible pitfalls. Mastering these casting methods volition empower you to compose much strong and maintainable C++ functions.

Knowing dynamic_cast successful C++

dynamic_cast is chiefly utilized for downcasting inside an inheritance hierarchy. Particularly, it makes an attempt to formed a pointer oregon mention to a basal people entity to a pointer oregon mention to a derived people entity. Dissimilar another casting operators, dynamic_cast performs a runtime cheque to guarantee the validity of the formed. If the entity being formed to is not really an case of the mark derived people, dynamic_cast volition instrument a null pointer (for pointer casts) oregon propulsion a std::bad_cast objection (for mention casts). This runtime kind checking makes dynamic_cast a safer action once dealing with polymorphism, arsenic it prevents undefined behaviour that tin originate from invalid casts. It’s indispensable to line that dynamic_cast requires runtime kind accusation (RTTI) to beryllium enabled, which tin somewhat contact show.

Exploring static_cast Performance

static_cast is a much versatile, compile-clip casting function. It tin beryllium utilized for a wider scope of conversions in contrast to dynamic_cast, together with conversions betwixt numeric sorts, conversions betwixt associated people sorts (some upcasting and downcasting), and equal conversions from void pointers. Nevertheless, static_cast does not execute runtime kind checking. It depends connected the programmer to guarantee that the conversion is legitimate. If you usage static_cast to execute an invalid downcast (e.g., casting a basal people pointer to a derived people pointer once the entity is not really an case of the derived people), the behaviour is undefined. Due to the fact that of this deficiency of runtime condition, static_cast ought to beryllium utilized with warning and lone once you are definite that the conversion is legitimate. Its chief vantage is its velocity, arsenic it doesn't incur the runtime overhead related with dynamic_cast.

'Regular Fashioned' Sorts and Casting Implications

The word "regular fashioned" is not a modular C++ word straight associated to casting however may conceptually associate to the ongoing government oregon "action" of an entity's kind throughout runtime. Deliberation of it successful status of however an entity’s government and information germinate done its lifecycle, peculiarly once contemplating polymorphism and inheritance. Successful the discourse of casting, this ongoing 'action' oregon existent kind of an entity turns into captious once deciding which casting function to usage. For case, once you person a basal people pointer, the 'regular fashioned' oregon existent derived kind of the entity it factors to determines whether or not a dynamic_cast is harmless and legitimate. If the underlying entity is so an case of the kind you’re casting to, dynamic_cast succeeds; other, it fails gracefully by returning nullptr (for pointers). This ties into the runtime dedication of an entity's kind, influencing the casting procedure.

For illustration, see this occupation:

  class Base { public: virtual void print() { std::cout << "Base\n"; } }; class Derived : public Base { public: void print() override { std::cout << "Derived\n"; } }; int main() { Base basePtr = new Derived(); // Points to a 'daily formed' Derived object Derived derivedPtr = dynamic_cast<Derived>(basePtr); if (derivedPtr) { derivedPtr->print(); // Output: Derived } else { std::cout << "dynamic_cast failed\n"; } delete basePtr; return 0; }  

The dynamic_cast succeeds due to the fact that basePtr genuinely factors to a Derived entity astatine runtime.

Knowing the existent, 'regular fashioned' kind helps guarantee harmless and accurate usage of casting operators. You ought to besides see Placing successful circumstantial bundle explanation with pip.

Cardinal Variations Summarized

To intelligibly exemplify the distinctions betwixt dynamic_cast and static_cast, present’s a array summarizing their cardinal options and utilization situations. This examination volition aid you take the due casting function based mostly connected your circumstantial wants and the flat of condition required successful your codification.

Characteristic dynamic_cast static_cast
Kind of Cheque Runtime Compile-clip
Condition Safer (performs runtime kind checking) Little harmless (nary runtime kind checking)
Usage Instances Downcasting successful polymorphic hierarchies Conversions betwixt associated sorts, numeric conversions, void pointers
Instrument Worth connected Nonaccomplishment nullptr (for pointers), throws std::bad_cast (for references) Undefined behaviour
RTTI Demand Requires RTTI (Runtime Kind Accusation) Does not necessitate RTTI

Once to Usage All Formed

Selecting betwixt dynamic_cast and static_cast relies upon heavy connected the discourse and condition necessities of your codification. Usage dynamic_cast once you demand to safely downcast successful a polymorphic hierarchy and tin spend the runtime overhead of kind checking. This ensures that you're lone working connected objects of the accurate derived kind. Usage static_cast once you're definite of the kind conversion and privation to debar the runtime overhead of dynamic_cast. This is communal for upcasting oregon changing betwixt numeric sorts. Nevertheless, ever beryllium cautious once utilizing static_cast for downcasting, arsenic it supplies nary runtime condition nett. Ever like condition except show issues dictate other. You tin besides publication much astir casting operators connected cppreference.com.

Successful decision, knowing the variations betwixt dynamic_cast and static_cast, and however they associate to the existent runtime kind of objects (the 'regular fashioned' kind), is important for penning strong and businesslike C++ codification. Piece dynamic_cast presents runtime condition done kind checking, static_cast supplies quicker compile-clip conversions. Selecting the correct casting function includes cautiously contemplating the commercial-offs betwixt condition and show, and making certain that you realize the underlying kind relationships successful your codification. You mightiness besides discovery invaluable insights successful this treatment connected the ISO C++ requirements concerning casting methods. By mastering these ideas, you’ll beryllium fine-outfitted to grip analyzable casting situations successful your C++ initiatives.


An Efficient Runtime Type System for C++ - Yaser Zhian (TGC 2017)

An Efficient Runtime Type System for C++ - Yaser Zhian (TGC 2017) from Youtube.com

Previous Post Next Post

Formulario de contacto