Boost logo

Boost :

From: Daryle Walker (darylew_at_[hidden])
Date: 2004-12-20 19:11:24


On 12/19/04 7:43 AM, "Dirk Gregorius" <dirk_at_[hidden]> wrote:

>> Does it really make any sense making only implementation noncopyable, rather
>> than interface? If you deal with interfaces only it won't save you from
>> errors like this:
>>
>> std::auto_ptr<Interface> create()
>> { return std::auto_ptr<Interface>(new Implementation); }
>>
>> void foo()
>> {
>> std::auto_ptr<Interface> a(create()), b(create());
>>
>> *a = *b; // oops, no error here, Implementation::operator=
>> // is not considered
>> }
>>
>
> I saw some code that declared the copy operations private in the base class.
>
> class Interface
> {
> public:
> virtual void f() = 0;
>
> private:
> Interface( const Interface& );
> Interface& operator=( const Interface& );
> }
>
> So in order to gain maximum style and correctness points I need to make both
> classes ( Interface and Implementation ) noncopyable? Which means both need to
> derive from boost::noncopyable?

I think that this is a bad idea. If "Interface" has no data members, then
it's better to leave the copying operations unspecified. Manually inserting
copy-blocking declarations does more harm than good. It does not provide a
ban on derived classes ever getting copy operations, since the derived
class's copy constructor can use _any_ base class constructor and the
derived class's assignment operator doesn't have to call the base class's
assignment operator. (A derived class can't have automatically defined copy
operations, though; the evil copying operations have to be explicitly
written.) Worse, the "Interface" class as given has no usable constructors,
because the private & undefined copy constructor STILL cancels the
automatically defined default constructor! Granted, the presence of a pure
virtual member function already bans creation of "Interface" objects, but no
derived classes can be made either.

As I implied, let the automatically defined copy operations for abstract
classes work. This applies to abstract classes with no data members that
have problems automatically managing their resources (includes classes with
no data members at all). For members that need explicit copying management,
like shared pointer class internals, then provide protected versions of the
standard copying operations. Ban the copying operations only if there is no
way to create sane copying semantics.

> BTW:
>
> Why is this possible? Does it make sense to dereference an interface?

No, it doesn't make sense for what you wrote next. It's possible because
C++ in general (along with C) does not censor what you do with return
values.

>
> Interface* p1 = make_interface();
> Interface* p2 = make_interface();
>
> *p1 = *p2;

Unless the "Interface" assignment operator is virtual, this will do slicing!
That will be very bad in general. Note that automatically defined
operations are never virtual. In the case here, making a protected
assignment operator may help by making the compiler spit out an access error
(unless this code is within a derived class's method).

> Or does your example only work with auto/smart pointers?

-- 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT hotmail DOT com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk