Adding a new legacy "interface" and virtual methods requires recompilation

There are existing answers that cover general cases, but they are a bit vague, and I have to be sure of that.

Consider:

  • An existing defined class derived from the abstract base class "interface".
  • A class is part of a library that is compiled into several DLLs that communicate with each other through an interface.

Then add:

  • The second "interface" from which a specific class will now be created (now it has two interfaces).
  • New virtual methods for a specific class accessed by the new interface.

Do I need to recompile every DLL that links this library, or just DLLs that use the new methods?

EDIT:

My original interface provides the dynamic method Dynamic(int OP, void* args) , can I add op, which adds a new interface?

How does COM manage to add new interfaces to objects without distorting existing interfaces? Does it contain interfaces, uses multiple inheritance, etc.

Let me outline how this works.

Library Static Binding Interfaces

 In statically linked library class Interface1 { virtual Method1() = 0; virtual Method2() = 0; } class NotReallyInterface2 : Interface1 { virtual Method1() = 0; virtual Method2() { // does something } } 

In dlls

 In A.dll Load statically linked library class A : NotReallyInterface2 { virtual Method1() { // does something } } In B.dll Load statically linked library class B: NotReallyInterface2 { virtual Method1() { // does something different } } 

I want to add

 class Interface3 { virtual Method3() = 0; } 

I have some problems here because my inheritance structure looks like.

 [a.dll [ library : Interface1 < NotReallyInterface2 ] < A ] [b.dll [ library : Interface1 < NotReallyInterface2 ] < B ] 

so i'm afraid

 [ a.dll [ library : Interface1 < NotReallyInterface2 ] < Interface3 < A ] 

will not work.

Edit 2

So, I found my problem. Apparently, other DLLs and executables are referencing my NotReallyInterface2 . This means that multiple dlls and exes build the same base class. Therefore, if these “copies” of the base class fail, the ship goes down. This means that I cannot change one method signature in NotReallyInterface2 .

This would work if no one referenced NotReallyInterface2 , and now I get it from the answers, and all this makes sense.

+4
source share
4 answers

You need to recompile those DLLs that reference the derived class directly. Those that only reference the interface will continue to work.

COM relies on just that. The COM ABI specification actually makes it necessary that every compatible C ++ compiler does not hang with vtables so that the interfaces stop working. That's why one of the main requirements of COM is that you never change the published interface by adding / removing / changing functions or providing it with a new base interface.

Adding a new interface due to the fact that it displays the old one and makes the implementation class from the new interface does not violate it; also does not have multiple inheritance from many interfaces in the implementation class.

A non-abstract class should not get in the way, but now you are out of COM guarantees. If this class has data members, it gets even worse. I think it would be safe not to recompile the code, but I would not want to rely on it anymore.

+4
source

Officially, any change to any class requires recompilation of everything related to this class. The C ++ standard, and most compilers produce documentation, makes no guarantees as to "what will happen if you change something in the class."

In practice, there are things you can do that will do the job. And there are things you can do that will surely make everything break.

The second class of the interface represents the second vtable, which, in turn, means differences in the class that inherits both classes. It is almost certainly in the “break all categories” category, it will cause problems all over the world that use this class in any way with regard to the “contents” of the class.

Is it possible to add a new class derived from the source class of the interface instead?

So, instead of:

  class Interface_A { public: virtual void func1(); virtual int func2(); ... }; class Interface_B { public: virtual int func6(); ... }; class myClass : public Interface_A, public Interface_B { ... }; 

do the following:

  class Interface_B : public Interface_A { public: virtual int func6(); ... }; class myClass : public Interface_B { ... }; 

This would (in most cases) make the vtable a little longer, which is much more acceptable for the rest of the code and for any code that ONLY uses the Interface_A functionality, it will not cause any problems. [If the compiler does a reasonable job - the standard still allows the compiler to hang everything if you do. But I worked for a company where we had a lot of code in which other parts of the system didn’t change, and we analyzed and looked at such things quite a bit.

+2
source

Adding a new interface adds additional virtual methods that change the vtable layout (an internal table generated by the compiler to route calls to virtual methods.) Thus, you need to recompile each module that uses the class (or at least each that creates / destroys or calls the virtual method in the class.)

+1
source

Assuming that the second interface does not repeat any full signature method from the 1st interface (in this case, you should use virtual inheritance) And in your implementation, the 2nd interface is actually the second:

 ImplClass : public Interface1, Interface2 

you do not need to recompile existing code that uses only the interface1. This is because ImplClass will now have two pointers to two vtables, but the first pointer will remain at the beginning of this class memory layout.

Also, if you used factory methods in your library, which means the client code always got the interface * by calling something like the Interface1 * CreateInterface1 () method implemented in the library (and never touched ImplClass * directly), and now this method has been recompiled, then you don't care, even the order of the interface.

0
source

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


All Articles