15

What does C4250 Visual C+ warning mean in practical terms? I've read the linked MSDN page, but I still don't get what the problem is.

What does the compiler warn me about and what problems could arise if I ignore the warning?

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 1
    The explanation in the MSDN article contradicts itself. "The one in class2 is inherited because it is a base class" - but class2 is the derived class, not the base class in their example. – MSalters Feb 03 '10 at 09:10
  • @MSalters: I can't see the contradiction. They don't use `class2` in their examples. In fact they never give an example of the text of the warning in their worked examples. – quamrana Feb 04 '10 at 07:53
  • @MSalters I suggest you to read it again! class2 is the BASE class. – CinCout Feb 26 '14 at 05:24

4 Answers4

28

The warning is pointing out that if any weak class operations depend on vbc virtual operations that are implemented in dominant, then those operations might change behavior due to the fact that they are bundled in a diamond inheritance hierarchy.

struct base {
   virtual int number() { return 0; } 
};
struct weak : public virtual base {
   void print() { // seems to only depend on base, but depends on dominant
      std::cout << number() << std::endl;
   }
};
struct dominant : public virtual base {
   int number() { return 5; }
};
struct derived : public weak, public dominant {}

int main() {
   weak w; w.print();    // 0
   derived d; d.print(); // 5
}

That is the behavior that the standard specifies, but it might be surprising for the programmer at times, the weak::print operation behavior has changed not because of an overridden method above or below in the hierarchy, but by a sibling class in the inheritance hierarchy, when called from derived. Note that it makes perfect sense from the derived point of view, it is calling an operation that depends on a virtual method implemented in dominant.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • 2
    Well what I dont get: How is determined which class is dominant? By order of the list of classed to inherit from? – flohack Feb 05 '15 at 11:53
  • @flohack: I am not sure that *dominant* vs. *weak* is the right terminology or whether it confuses more than helps... If you think of an inheritance graph, with nodes being types and arrows being inheritance relationships, in the final object there will be multiple paths from the bases to the *one* complete object. In each path there will be *one* final overrider for each virtual function in the bases, in one of the types, the one closer to the *complete* object. – David Rodríguez - dribeas Feb 05 '15 at 14:17
  • 1
    ... you can think of virtual inheritance as branches in the graph, if the final overrider for one of the branches is above the split point, and the other branch provides a later overrider, it replaces the overrider for both branches. At the level of the *complete* object (the real type constructed), the final overrider in all paths must refer to the same type, if it doesn't then you get an error at compile time. – David Rodríguez - dribeas Feb 05 '15 at 14:23
  • ... the warning indicates that the compiler found a *split* in graph above, and that the current type is calling a virtual function whose final overrider is on or above the split point. This means that the behavior of this function, in this branch of the graph can be affected by types in a different branch of the inheritance graph of the complete object. The `print` function can depend on a type that is neither above nor below `weak` in the hierarchy. The one that the example calls `dominant` (it is only *dominant* in the sense that it dominates over the base, which is what this type depens on – David Rodríguez - dribeas Feb 05 '15 at 14:26
  • Very useful, thanks. However, I only understood after the comments. Maybe it's worthwhile to edit the answer (and add the images)? – BmyGuest Mar 21 '17 at 10:45
18

It means that the compiler has noticed that you are using a lesser known feature of virtual inheritance that it has a name for. I've no idea why they thought it was a good idea to make it a warning but it has no practical significance; the code should work as the language specifies, it's not pointing out a compiler deficiency or anything.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • No kidding, and to make it even more mysterious why is it a level 2 warning and not a level 4 (like "unreferenced local variable" or "variable initialized but never used")? – davidbak Mar 15 '17 at 01:07
3

In VS2012 you can get this warning for "nothing" but for inheriting a class from iostream. The MS feedback article states that this warning can be ignored in this case.

If you don't want to suppress this kind of warnings but want a cross-platform code that doesn't produce this garbage warning under vs2012, an article on C4250 suggests at CodeInPro to add these do-nothing lines to your code in the class that inherited from an iostream:

void _Add_vtordisp1() { } // Required to avoid VC++ warning C4250
void _Add_vtordisp2() { } // Required to avoid VC++ warning C4250
DanielTuzes
  • 2,494
  • 24
  • 40
3

In the linked example you have diamond which inherits both weak and dominant, which both inherit virtually from vbc, but only dominant overrides func()

There is a problem in C++ when you have such a structure when you don't use virtual inheritance. However, with virtual inheritance, the problem is solved, so the warning is just information telling you that if:

  1. You hadn't used virtual inheritance, OR
  2. weak had implemented func()

then you would get a compiler error.

So, my opinion is that if you know what you are doing you can safely disable this warning for the whole of your project.

quamrana
  • 37,849
  • 12
  • 53
  • 71