понедельник, 31 января 2011 г.

Private inheritance and std::auto_ptr

Some time ago I have encountered a problem. When I was writing implementation of an interface class, I forgot to specify inheritance access-specifier, so the private-inheritance is assumed by default. It is illustrated in the following example:

class A
  virtual void Method() = 0;
  virtual ~A();

class B: /*private*/ A
  virtual void Method();

And I used a factory to create an instance of the class B:

std::auto_ptr<A> CreateB()
  return std::auto_ptr<A>(new B());

As you must know, private inheritance limits access to a base class for B class clients.  But technically it is still accessible, see 11.2 paragraph 3 of the C++ standard:

Because of the rules on pointer conversions (4.10) and explicit casts (5.4), a conversion from a pointer to a derived class to a pointer to an inaccessible base class might be ill-formed if an implicit conversion is used, but well-formed if an explicit cast is used.

The previous code doesn’t use an explicit cast, but still compiles without any errors and warnings by Microsoft Visual Studio 2005 SP1 C++ compiler. It is known that this version has a bug in auto_ptr implementation, that allows any pointer to be passed in the constructor. But my header files was already patched (once I have spent several hours debugging a code). Then I wrote some more examples to test compiler behavior:

A* pa = new B();              // compile error, ok
B* pb = new B();

std::auto_ptr<A> a(new B());  // compile error, ok
a.reset(pb);                  // compile error, ok

std::auto_ptr<B> b(new B());
a = b;                        // compile error, ok

// oops! this works! o_O
return std::auto_ptr<A>(new B());

I’ve also tested this examples with the Microsoft Visual Studio 2008 and 2010.  Both still compiles without any errors and warnings, but the last displays IntelliSence error:


Fortunately I also compiled my code with GCC 4.4.3 compiler, and it works as it should be, producing an error: “A” is inaccessible base class of “B”. This is no a serious error, but this remind us that it is good when compiler finds out our typos, malformed and dangerous expressions. And it is good to set a maximum warning level when compiling code or use several compilers. As proverb says, two heads is better then one.

This is my first post in English, so feel free to send corrections. And of course, comments are welcome!

Комментариев нет:

Отправить комментарий