Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Conversations: Access Restrictions


February 2001 C++ Experts Forum/Conversations

Boom.

The distant thundering quickly passed. It was faint, felt more than heard. The excavation teams were at work again.

"I wish..." Jeannine started, then trailed off.

"I know." I buried my face in my work. After a long time, I added: "I wish I could send mail home too. But the comms should be working again soon."

"They do work," Jeannine said.

Boom. Another distant explosion.

"Yeah, but while the dome's systems are damaged, it makes sense to reserve them for only emergency traffic. We just aren't being given access, for now. That's reasonable." My heart wasn't in the words.

There was silence again, for a time. Finally, Jeannine whispered: "Yeah. Well, that's what they say, now isn't it?"

"That's right. It's just temporary access restrictions. I don't like it, either, but surely you don't think they're...." It was my turn to trail off.

Boom.


"Boom."

That was all the sticky note on my monitor said. Well, that and a filename. I recognized the file — it was a utility class I had added to the project a while back. The note was written in the Guru's distinctive handwriting, but I had no clue what it meant. The Guru wasn't in yet, so I couldn't ask her.

Just then, Wendy, the programmer in the cubicle next to mine, came in and flopped down in her chair. I gophered up, hoping she'd be able to make sense of it. She looked haggard, resting her head on her hands. "You look like you had a rough weekend," I ventured.

She nodded without looking up. "When I got home Friday, the carbon monoxide detectors were beeping away — turns out the furnace was clogged up. We had to spend the weekend at a friend's house, until it was fixed. I couldn't sleep a wink — I kept wondering what would've happened if we hadn't installed the detectors [1]."

"Wow, that was a close call," I commiserated, making a mental note to double-check my detectors. "Is everyone OK?" Wendy nodded. I decided she needed a distraction, so I mentioned the note to her and asked her what it might mean.

"Wait a minute," she said. "The Guru left that note on your monitor?" I nodded. "My friend," she said, "it sounds like you may have just pulled a Bob."

I was aghast, speechless, at such strong language. "You're joking!" I blanched. Bob was the worst programmer ever, and I had made it my personal mission to thwart him and his poor programming style every opportunity I got.

Wendy shook her head, dead serious. "Nope. He's usually the only one who gets those cryptic notes, and if you got one, then you must've been a very bad boy. Let's have a look at that source file." She turned to her computer, logged in, and called up the file in question.

I dragged over a chair. "Everything in here looks good to me," I said, peering over her shoulder.

Wendy jumped slightly — she must have been more stressed than I realized. "It seems OK on a quick glance," Wendy agreed. "Maybe a diff against the previous revision will give us some clues." I watched as she used our revision control system to show the difference between the two versions of the file. I was impressed — I was still trying to master the basic checkin/checkout syntax, and here she called up a diff between two revisions in no time at all. I was still trying to sort out the commands Wendy had used when she spoke up.

"Well, here's something, but it's really minor," she said, pointing to the screen. "You've changed some of the class data members."

I peered closer at the screen. "Yes, I reworked the implementation slightly. I changed the three separate doubles, representing the object's location, into an array of three doubles. It made some member functions much more efficient. But the members are all private, see?"

class Point
{
private:
    double location[3]; // x, y, z coordinates.

public:
    void setLocation(double x, double y, double z) { 
        location[0]=x; 
        location[1]=y;
        location[2]=z;
   }

    void getLocation(double &x, double& y, double &z) {
        x=location[0]; 
        y=location[1];
        z=location[2];
    }
};

Then I noticed a blank line at the top of the file that the diff viewer indicated had changed. "Now, why would the viewer highlight that line?" I wondered out loud.

"Probably just white-space changes," Wendy surmised. "Here, let me set the viewer to ignore white space." A few keystrokes later, and... the line was still highlighted. I placed the cursor on the line, hit the "End" key — and froze in horror at the sight in front of me. Indented way off to the right, out of normal view, was this statement:

                                            #define private public

Wendy and I looked at each other. "Bob!" we chorused.

Bob, as it turned out, was already walking toward us. The Guru wasn't the only one who could show up at the most appropriate moment. "Hey, Junior," he said, "I just came by to see if you've fixed the problem yet."

I closed my eyes and counted to ten. Slowly. Then I counted back down to zero. I held up the sticky note: "Do you mean this problem?" I asked sweetly.

"Heh. Yeah, that's the one. Her Weirdness left it on my monitor. When you changed the x, y, and z members to that array, it broke a raft and a half of my code, so I passed it on to you. Fix it, and quit messing things up from now on, will ya."

"Bob, what's the idea of this #define statement?" I pointed to the offending line.

"Oh, that," Bob chuckled. "Pretty cool, eh? My code needed direct access to the coordinates. Efficiency, y'know. At first, I just had the #define statement in my own code, but I was using it a lot, so it was easier to add it to your header. I'm doing a lot of number crunching, and I can't afford the overhead of the accessor functions you provided. But then you got rid of the individual doubles, for that array. And my code went 'Boom!'"

"Boom, indeed." As if on cue, we heard the Guru's voice. We all jumped a little. She used a finger to pointedly move her glasses back up the bridge of her nose. "And that, you purveyor of programming perversions," she rebuked, "is why I left the sticky note on your monitor. You violated the class's encapsulation by attempting to subvert the access privileges. You violated the One Definition Rule by changing private to public in your code. You must fix your code to use the accessor functions."

"I already said, I can't afford the overhead of the accessors, dearie," bristled Bob. "I have to-"

"Silence!" the Guru interrupted. "The accessors are inline and should cause no overhead." Bob started to protest again, but the Guru headed him off. "However, in order to avoid the root of all evil [2], we will create a test harness to demonstrate the actual costs of the accessor functions. Meanwhile, clean up that unseemly code. Then read and meditate on 1 Meyers 20 [3]."

Bob grumbled as he left for his cubicle. The Guru simply stood silently until he was gone and then led me back to my own cubicle.

"My apprentice," she said, her voice soft again, "please write a test harness that will time the cost of direct access, against inline accessors and non-inline accessors. Be sure that the non-inline accessors are in a separate translation unit. While you are at it, an inline operator [] would be useful."

I thought about that for a moment. "You mean like this?" I began writing on my whiteboard:

class Point
{
public:
    inline double operator[] (int index)  const {
        return location[index];
     }
};

"Very good, my apprentice. You have remembered the blessings of const-correctness. But now, write it so that it can serve not only as an accessor, but as a mutator as well. What other benefits can you derive from this function?"

I thought about it for a moment. "You can do bounds checking on the index." I revised the scribbling on the whiteboard:

class Point
{
public:
    inline double &operator[] (int index) {
        assert(index >=0 && index <= 2);
        return location[index];
     }
};

"Hey, cool!" This, I liked. "The bounds checking has no performance penalty in release mode."

The Guru nodded. "And," she added, "with a good optimizing compiler, the compiler should be able to generate code that is as efficient as accessing the members directly, with the added blessings and safety of encapsulation."

"So," I mused, "there really is never any reason to have a public data member, is there?"

The Guru paused a moment before answering. "In most cases, no. However, if the class is merely a convenient aggregation of data, with no object being modeled — that is to say, a C-style struct of data with no additional behavior — then it would be reasonable to have all data members public [4].

"You can expose private members through accessor and mutator functions — but only if it is really necessary. An excessive amount of Get and Set member functions — including ones that are disguised as operator [] — indicates that you are not thinking of the blessings of encapsulation. If your tests indicate that the accessors are providing a substantial run-time penalty, then you can improve the speed by making the accessors inline. Of course, the savings and penalties will vary from compiler to compiler — hence the need for the test harness."

"I'll get right on it, boss," I replied cheerfully. She smiled, folded her hands and silently walked away. I sat down to write the test harness. The results, at least on the compiler I was then using, were quite interesting [5]:

  Approximate run-time in milliseconds
Implementation Optimizations off Optimizations on
1: direct access 1061 251
2: inline accessor function 1673 240
3: out-of-line accessor function 1662 1432


Boom.

"I don't like it," Jeannine repeated. "They say the dome is damaged because of an accidental internal explosion, so we don't have access to go there, but work goes on in there, and people with higher clearances have been allowed in and they never come out again. They say the long-range comms systems are damaged and are restricted for emergencies only, but the only real effect I can see is that we can't communicate with anybody outside near-Jupiter space."

"So?"

"I don't like it."

Boom.

We said no more for some time, and eventually the distant thundering stopped, but the resulting silence was worse than the faint noise had been. A few minutes later, Jeannine frowned, got up, and left.

Notes

[1] Note from the authors: this situation actually happened to me (Jim) recently. I urge all readers to install carbon monoxide and smoke detectors and ensure they are well-maintained. I know it's the best investment I've ever made! Contact your local fire prevention office for information and assistance.

[2] "Premature optimization is the root of all evil" — Donald Knuth. Depending whom you believe, he said it in one or more of: "Structured Programming with go to Statements" (Computing Surveys, Vol. 6, No. 4, December, 1974, page 268), Literate Programming, or Computer Programming As an Art (1974).

[3] Scott Meyers, Effective C++, 2nd edition, Item 20: "Avoid data members in the public interface" (Addison-Wesley, 1997).

[4] C++ FAQ Lite, Marshall Cline, http://www.parashift.com/c++-faq-lite/classes-and-objects.htm#[7.8].

[5] The source code and full details of this test are available on the CUJ website.

Jim Hyslop is a senior software designer at Leitch Technology International Inc. He can be reached at [email protected].

Herb Sutter is chief technology officer of PeerDirect Inc. and secretary of the ISO/ANSI C++ standards committee. He can be reached at [email protected].


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.