Dynamic change of virtual pointer at runtime

So, let's say I have two classes that inherit a base class that has a pure virtual function. Both classes implement their own version of this function, but do not add additional member variables, so they are the same size. Now sometimes, in the middle of program execution, I want to convert one class to another without copying all its data. So basically I want it to use a virtual table of another class. Is there a way to travel?

+4
source share
6 answers

A portable way to do this is to implement your own class system, which actually has virtual pointers that you can copy.

There is no such thing as a virtual pointer in standard C ++.

+4
source

Nope. As for the language, there is no such thing as a virtual table, not to mention the rules of how it looks / what it contains / where it is stored.

Some form of composition is probably more suitable for your task.

+4
source

One young colleague from Andersen Consulting (now Accenture) in Norway once approached me with a serious problem. Their applications developed in Visual Basic have been loading for a long time. He suspected this could be because they put each class in their own DLL?

Fearing the worst, I asked further. And yes, they also had problems with arbitrary accidents, etc.

He suspected that otherwise unexplained accidents could be due to their inventive scheme for changing the type of an object at runtime by replacing the vtable pointer?

I suggested that perhaps they should not really do this. He looked at me skeptically and ventured that they did not have time to do something from scratch again. In fact, they were already stretching it, and there were different problems with it, like their project manager, insisting that they work on a client site and do not participate in obligatory meetings. For me, it sounded like mushroom control (keep them in the dark when your head pops up, cut it): these things often go together.

In any case, I give you the same advice: do not do this.

Perhaps you can instead implement fast move operations to move data from a to b?

Or maybe you find that all this in the case of premature optimization?

Cheers and hth.,

+4
source

Is there a way to travel?

Absolutely not. The specifics of implementing virtual functions are not defined by the specification, and therefore there is no portable way to pretend that one virtual class is another.

+3
source

Like other answers, actually changing the vtable, of course, is not portable.

However, there are several workarounds that can allow you to perform similar semantics without actually changing the class type:

This simplest solution is to "collapse its" inheritance with an enumeration describing the current implementation:

class MyClass { public: enum DerivedType { A, B }; private: DerivedType myType; public: void myVirtualFunction() { if (myType == A) myAFunction(); else myBFunction(); } } 

You can also use a function pointer as an open member variable that is set to a function indicating the type of class. Then you can set a pointer to a function of another class to "change its type"

Since you mention that you want to avoid copying data, you can save your different classes, but link pointers to links to all your member variables so that you can quickly create new objects of the opposite type.

+3
source

Although this question is old, I would like to discover a way to do this. (Not quite sure about portability)

From what I understand, you have class B and C that inherit from some class A , and there is only one virtual function between them. (The method presented here works if B and C also not connected.)

 class A { public: virtual std::string hello() = 0; }; class B : public A { public: virtual std::string hello() { return "B"; } }; class C : public A { public: virtual std::string hello() { return "C"; } }; 

And then you want to take B to C and then call hello and get "B" .


Thus, there is a way to create an flooded version of boost::any that will bring anything if it suits :)

 struct parent {}; template< typename T > struct child : public parent { child(T const& t): item(t){} mutable T item; }; template< typename T > T& as(parent const & p) { return static_cast< child< T > const& >(p).item; } 

Then mix everything together:

 B b; parent* p = new child< B >(b); std::cout << as< C >(*p).hello() << std::endl; // ==== OUTPUT ==== // B 

You can see the code in action here .


To take another step, we can create a function that converts from one type to another without providing the back end of the mosquito about what happens between them.

 template< typename TO, typename FROM > TO& convert(FROM const& from) { parent* p = new child< FROM >(from); return as< TO >(p); }; 

It can be run here .

(I realized that I skipped inheritance in these code link examples, but after reading the question, I think it was really desirable. So, to see the test without inheritance, go here )


Some other code that I started playing with something that I thought could help too ...

 #include <iostream> #include <string> class B { public: virtual char hello() {return 'B';} }; class C { public: virtual int hello() {return 65;} }; struct parent {}; template< typename T > struct child : public parent { child(T const& t): item(t){} mutable T item; }; template< typename T > T& as(parent const & p) { return static_cast< child< T > const& >(p).item; } template< typename TO, typename FROM > TO& convert(FROM const& from) { parent* p = new child< FROM >(from); return as< TO >(*p); }; int main() { B b; std::cout << convert< C, B >(b).hello() << std::endl; C c; std::cout << convert< B, C >(c).hello() << std::endl; } // ==== OUTPUT ==== // 66 // A 

Figured out how to do it all inside the conversion function:

 template< typename TO, typename FROM > TO& convert(FROM const& from) { struct parent {}; struct child : public parent { child(FROM const& t): item(t){} mutable FROM item; }; struct sibling : public parent { sibling(TO const& t): item(t){} mutable TO item; }; parent* p = new child(from); return static_cast< sibling const& >(*p).item; }; 
0
source

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


All Articles