December 16, 2017
Hot Topics:


  • February 27, 2004
  • By Kate Gregory
  • Send Email »
  • More Articles »

Is This on Purpose?

So now that you've seen this phenomenon in action, how about giving it a name? Actually, it has two. This behavior is often referred to as "hide-by-name" and it's the way C++ is designed to work. It's also referred to as shadowing. It's a language design decision meant to protect you from base class changes. Consider this pair of classes:

class A
   int i;
   void f(int ii);
class B: public A
   void f(long ii, char* ss);

Imagine that you wrote B, you didn't write A, and that these classes live in some sort of distributed world where someone (a library author?) might add functionality to A without your realizing it. You've written your overload to take a long "just in case," but you actually pass ints to it all the time:

char* s = "Hello";
int i=3;

Then, one day, someone adds an overload to the base class that takes an int and a char*. That's a more precise match, so should the compiler suddenly start calling the new base class overload for you? With hide-by-name, all the base class overloads "disappear" when you write any overload in the derived class, guaranteeing that only overloads you wrote will be called—unless you ask for them specifically by using the scope resolution operator (::) as I did earlier with b.A::f(4).

This behavior in C++ makes sense, but it worries some people who feel it violates substitutability. If you're using inheritance properly, your derived classes should meet the IS A test. Everything you can do with a BankAccount you should also be able to do with a SavingsAccount or a RetirementAccount. Hide-by-name doesn't violate this rule, as long as you've cast your derived class pointer or reference to a base class pointer or reference. In code that knows this is a derived object, the derived methods shadow the base methods.

Does C# Shadow? Does VB?

You may wonder whether other object-oriented languages implement hide-by-name like this. Here are those same two classes in C#:

public class A
   protected int i;
   protected String s;

   public A() {s=null;i=-1;}
   public void f(int ii) {i=ii;s="";}
   public void f(String ss) {i=0; s=ss;}
   public void report () { Console.WriteLine("{0} {1}", i,s);}

public class B:  A
   public void nothing() {;}
   public void f(int ii, String ss){i=ii; s=ss;}

And here's a main that uses them:

A a = new A();
B b = new B();

So, here's something weird: This code compiles just fine and runs just fine. C# doesn't use hide-by-name; it uses hide-by-signature. Is that a positive, or a negative? The answer probably varies from project to project. Sometimes you want your derived class protected against changes in the base class; other times you might like still being able to call all the base class methods even though you've added some overloads in the derived class. (In C#, you can use the keyword new to get shadowing, and, in VB.NET, you should use either Overloads or Shadows to tell the compiler what you want. Shadows is the default.)

Where Does this Leave the C++ Programmer?

What should you do if you're in C++? If you want shadowing, do nothing. If you want to be able to call some methods from the base class, write explicit wrappers for them:

   void f(int ii) {A::f(ii);}
   void f(char* ss) {A::f(s);}

This makes your design obvious and undoes the shadowing. This leaves control, as usual for C++, in the hands of the programmer. Now that you know what the default behavior is, you can step up and change it if you want. And, you can add another tally to the "differences between C++ and C#" list, too.

About the Author


Page 2 of 2

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us
