-3

One line touted in discussions about what good C++ looks like is "you only pay for what you use". I have heard this used as justification to not use inheritance/polymorphism constructs and the idea of coding to an interface, because these constructs will require use of a v-table at run time for something known at compile time.

Is this true? Does basic OOP break a major tenet of C++ (specifically does the idea of "coding to interfaces" break the idea of "you only pay for what you use"?

old_timer
  • 69,149
  • 8
  • 89
  • 168
tjcertified
  • 694
  • 7
  • 18
  • 1
    Polymorphism should be used for when the types are NOT known at compile-time (e.g. when the object type can be selected by user input) – M.M Nov 09 '18 at 02:40
  • 1
    You only pay for polymorphism if you use, in accordance to the phrase. If you don't use 'virtual' you don't pay for it. If all types can be statically known at compile time you don't need polymorphism, so don't use it and you won't pay for it. C++ is not designed to prevent you from using something you don't really need. If you use something you don't need you still pay for it. – François Andrieux Nov 09 '18 at 03:09
  • Note that inheritance and OOP is not the same thing. You can use one without the other. You can have objects that don't use inheritance and you can use inheritance for non-OOP purposes like template metaprogramming. – François Andrieux Nov 09 '18 at 03:12
  • Inheritance is _of course_ part of OO and can among other things be used to design an interface for inherited classes to use. Similarly, polymorphism is merely a term for using an inherited instance and passing that to parent classes without the need to change the interface. All of this is _program design_ and big picture issues, completely language agnostic. There is no relation between polymorphism and user input. A program implementing polymorphism might not even have user input! – Lundin Nov 09 '18 at 08:59
  • That being said, inheritance is most of the time an overrated OO feature that should be used with caution. Since during the first program design stage, it is very difficult even for veteran designers to predict the needs for a class to evolve during future program expansions. Often such laid-out interfaces become cumbersome and a burden, if maintainers aren't allowed to go back and change the original interface. Similarly, maintainers who inherit classes that weren't designed for inheritance can create all manner of pitfalls. – Lundin Nov 09 '18 at 09:00
  • As for the question, these are broad program design philosophy issues: performance and maintainability are often conflicting interests. Programs that use careful design _will_ end up performing worse than programs written entirely in raw assembler. They can however be ported, maintained and expanded without turning into an unholy mess of tight coupling. Lots of C++ programmers have delusions that all the complex language features aiding program design come without a cost. This is of course not true. A skilled designer seeks a middle ground between performance and maintainability. – Lundin Nov 09 '18 at 09:11
  • @Lundin you should turn that last comment into an answer. – tjcertified Nov 09 '18 at 18:18
  • @M.M I'm going to add that polymorphism should be used in cases when all types are known at compile time as well. Its useful for collections of similar, but not identical objects, whether they're known at compile time or not. – Russ Schultz Nov 10 '18 at 19:52
  • @RussSchultz you can use templates instead of polymorphism in that case – M.M Nov 10 '18 at 21:54
  • This idea is partly to support ease in unit testing, so does one use mocks for headers in a unit test instead of interfaces/abstract classes? – tjcertified Nov 13 '18 at 17:33
  • @FrançoisAndrieux OOP means different things for different people. Sometimes, slightly different things; sometimes, barely related things. It isn't a very useful term. – curiousguy Nov 15 '18 at 19:33

2 Answers2

2

Use the right tool for the right job.

A v-table is useful when the exact type of a certain object cannot be known at compile time. If this applies to your program, then you are paying for what you use. If it does not apply, then there are ways to implement safe polymorphism without introducing a v-table (use no virtual functions; make the base class destructor protected).

There is no inherent contradiction here, but there is a requirement to understand the tools being used. It is not hard to use a sub-optimal tool and end up paying for more than what you use. (You could say the same thing about algorithms -- it is not hard to use a sub-optimal algorithm and end up using much more time/space than what you need. That's not a fault of the language.)

JaMiT
  • 14,422
  • 4
  • 15
  • 31
  • I come from primarily C#, and one prominent way to allow for easy unit testing in C# is to code to interfaces. Is there a C++ equivalent, so that I can use the right tool for the right job (in this case, testing)? – tjcertified Nov 27 '18 at 19:20
  • @tjcertified that looks like a new question to post – JaMiT Nov 30 '18 at 20:30
-1

The C++ polymorphism/object model was one of the first things added to the language, and it was added before that idiom was adopted.

It is a specific object model with certain trade offs, advantages and disadvantages. Variations on it would permit other tradeoffs; like adding types at runtime, replacing methods on a per-object basis, sparse vtables, etc. Or even splitting vtables from instances (so you can have packed arrays of same type more efficiently).

So yes, you can easily pay for unused features when you use vtables and rtti. And alternative models could save resources/time/etc, or permit alternative solutions.

On the plus side, metaclasses could permit rewriting interface/implementation go nearly arbitrary object model variations.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524