This is normal for static_cast pointer void *

For example, suggest map<int,void*>hold , where void* always stores pointers from classA , is it safe to return it again through static_cast?

 classA* ptr = static_cast<classA*>( holditerator->second ); 

The reason void* used because hold is a member of the class defined in the header used by some cpp files that do not know what classA . I would have to include the classA header of the definitions in these cpp files, which could not be executed for many reasons.

+6
source share
3 answers

Yes, static_cast OK in this case and the right thing to use.

I have to ask why you do not store classA* pointers in the first place. If you want to place the pointers of derived classes into it, then beware , before you put them on the map, you need to raise or not convert (implicitly or explicitly) the pointers of derived classes to classA* .

But even if you put class pointers on the map as well, a base class pointer will suffice, because a derived class pointer is implicitly converted to a base class pointer.

The reason void * is used is because hold is a member of the class definition in the header used by some cpp files that don't know what class A is.

This can be a good reason to prevent overlay violations.

I would have to include the heading of classA definitions in these cpp files, which cannot be executed for many reasons.

This is most likely not necessary in your case. Adequate declaration. If the header knows what fits on the map but just wants to avoid including additional headers, this is the way to go.

+13
source

As Johannes explained, static_cast is fine. Another way to prevent ClassA dependencies in cpp files is to use the pimpl idiom .

 // in header file class classB { public: classB(); ~classB(); private: class impl; unique_ptr<impl> pimpl; }; // in implementation file #include "classA.hpp" class classB::impl { std::map<int, classA> hold; // hidden in implementation file }; classB::classB() : pimpl{ new impl{ /*...*/ } } { } classB::~classB() { } 
+6
source

Writing void * in the header just because map users do not need to know about the actual type is not a good idea, since you lose type safety everywhere in your code, including places that know about ClassA.

Consider

  • ClassA output from a class that every part of your code can know about,
  • transferring the map to an object that provides an interface to those parts of the code that should deal with the map, but not with ClassA,
  • declaring but not defining the ClassA class in your header file (it can be dangerous if objects are destroyed in some place where ClassA is declared but not defined),
  • using patterns
  • an implementation of the class containing the map as a derived subclass, so that the display field can be placed in a derived subclass.

Point 5: Illustration (= template template)

Instead

 class Containing { private: map<int,void*> myMap; public: void somePublicFunction () { // ...implementation } }; 

you write

 // Containing.h class Containing { protected: virtual void doSomething () = 0; public: static Containing* Create (); void somePublicFunction () { doSomething (); } virtual ~Containing () { } }; // Containing.cc #include ContainingImplementation.h Containing* Containing::Create () { return new ContainingImplementation; } // ContainingImplementation.h / cc class ContainingImplementation : public Containing { protected: virtual void doSomething () { // ... } private: map<int,ClassA*> myMap; public: virtual ~ContainingImplementation () { } }; 
+2
source

Source: https://habr.com/ru/post/923734/


All Articles