Channels ▼

Al Williams

Dr. Dobb's Bloggers

Pure Virtuousness

July 13, 2012

But there are also things the C++ compiler won't do. For example:

  ademo demo_obj(5);

You can't do that because a is private. In the C version, you could easily pull out anything you want from the structure. It is all visible all the time. This is poor for encapsulation. Classic BASIC programmers get bogged down with global variables, and C provides local variables. Same idea. C makes all functions and structure members visible to everyone, where C++ scopes them so you only see them in certain contexts.

Here's the key, though. In reality, the code the C++ compiler generates is exactly the same as what a C compiler would generate. In fact, early C++ "compilers" were just front ends to the C compiler. So while your C program can't access demo_obj.a, that usually doesn't mean the generated code would not allow it (for example, in the case of an error). It just means that the compiler won't give you a way to express that access. So, like I said, sometimes the compiler is preventing you from doing things (for your own good). This is in stark contrast to classic Java running bytecode where the JVM may actually enforce things at runtime.

The LCD class library is a good example of this. It uses pure virtual functions for things it doesn't know how to do (like write to your LCD). That makes the class abstract — you can't construct objects of this type because you didn't give the compiler the whole definition. The =0 behind the getInput() and output() tell the compiler that these functions must appear in a derived class unless the derived class is also abstract.

What's the value to this? The base class can make calls to things like output() even though it doesn't know how it works. Presumably, if an object is actually instantiated some code will exist and that's what gets called. The pure modifier prevents you from creating a class that can't do anything.

Embedded C++ compiler support isn't always so great. Usually vendors that specialize in compilers have great offerings since that's their way of making a profit. But open source or vendor-supplied compilers — even when based on GCC — sometimes have quirks and many of those quirks are related to C++.

The Atmel AVR is a great example. There is a very nice GCC port for this processor and I use it quite a bit. But the C++ support is iffy, at best. For example, the compiler doesn't handle pure virtual functions.

Does it matter? Not really. If you stop and think about it, if the lcdui class provided empty output and input functions, what's the worst that could happen? You might accidentally instantiate the class and it won't really do anything. Just like C.

On the other hand, if I am running Linux on an ARM processor, I still want the compiler to help me find my mistake, so I don't want to just not use pure virtual functions. Consider this change to the class definition:

  // get an input code
  virtual INTYPE  getInput(void) PURE;
  // Write to the LCD
#ifndef NOSTRING
  virtual void output(std::string &ostring) PURE;
  virtual void output(const char *ostring) PURE;

Further up in the header I have:

#ifndef NOSTRING
#include <sstream>
#include <string>
#include <cstdlib>
#include <string.h>
#include <stdlib.h>

// not all compilers like pure virtual
#ifndef NOPURE
#define PURE =0
#define PURE { }

Did I forget to mention the AVR runtime doesn't support C++ strings either (or, at least, the version I am using doesn't). By defining NOSTRING and NOPURE in the makefile, it is possible to get a clean compile with the AVR compiler (or tools with similar limitations) and empty function bodies for pure virtual functions. On more sophisticated compilers, I get essentially the same code, but I get better error checking.

I am keeping the lcdui project up to date as I make changes, so if you pull the code off subversion, it might be slightly different. But the idea is the same: Use C++ features where they make sense and slip back to regular C where they don't. Of course, someone always asks: "What about the performance of virtual functions?" Well, what about it? Pure functions really have to be virtual (think about it). Engineering discipline demands we think about how much performance it really takes and not just base it on opinion. That's a future topic, though.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.