Avoiding Virtual Destructor with boost::noncopyable

Started by
5 comments, last by Nitage 15 years, 9 months ago
I'm just wondering if this works the way I think it does. :-) If I have a class that I don't want to allow to be copied, deriving from boost::noncopyable does the trick. If boost::noncopyable is the only base though, can I avoid the vtable and virtual destructor altogether via private inheritance?
class widget : private boost::noncopyable {
public:
    widget();
    ~widget(); // Not virtual!
};
Doesn't this result in widget having a hidden boost::noncopyable member? And, if this is true, doesn't it still make it uncopyable since the compiler cannot deduce how to copy this member? I know avoiding a vtable and virtual destructor may not be warranted, but if I can, why not? :-) Thanks!
Advertisement
Well, sure. You could also literally have a boost::noncopyable member. But why bother? boost::noncopyable doesn't declare a virtual destructor, so there won't be a virtual destructor unless you declare one. And the only reason you'd declare one (other than actually needing one further down the inheritance chain) is if you planned to pass around boost::noncopyable pointers, which would be bizarre in the extreme.
struct MyNonCopyableFoo {private:  MyNonCopyableFoo(const MyNonCopyableFoo &ff) {}  ... operator=(...) {}};


Boost is convenient, but one doesn't always have to hang on to it for everything.
Quote:Original post by Antheus
struct MyNonCopyableFoo {private:  MyNonCopyableFoo(const MyNonCopyableFoo &ff) {}  ... operator=(...) {}};


Boost is convenient, but one doesn't always have to hang on to it for everything.

lol, I've thought about this also. It is pretty trivial to implement an uncopyable class.

Thanks for the insight.

EDIT:

One good thing about using boost::noncopyable is that it makes what you're trying to accomplish very clear.
Quote:Original post by GenuineXP
I'm just wondering if this works the way I think it does. :-)

If I have a class that I don't want to allow to be copied, deriving from boost::noncopyable does the trick. If boost::noncopyable is the only base though, can I avoid the vtable and virtual destructor altogether via private inheritance?

*** Source Snippet Removed ***
Doesn't this result in widget having a hidden boost::noncopyable member? And, if this is true, doesn't it still make it uncopyable since the compiler cannot deduce how to copy this member?

I know avoiding a vtable and virtual destructor may not be warranted, but if I can, why not? :-)

Thanks!


Inheritance results in the derived class having a sort-of "member" of the base class type, sometimes called "the base class part of" the object (when there is only one), or "a base" (analogously to "a member"). That has nothing to do with whether the inheritance is public, protected or private.

The compiler can't copy boost::noncopyable objects, and thus it can't copy objects which include them as a member or base. Using it as a base rather than a member is considered idiomatic for some reason.

boost::noncopyable doesn't declare anything virtual, because it doesn't need to. The way to avoid creating a vtable and so forth in the derived class is to do nothing, i.e. not put in a virtual destructor. (Note that in C++, we have the rule of "once virtual, always virtual": in order to have a base that is virtual, we have to include that base in the object's data layout, which means we have to allow for a vtable anyway - assuming that it's implemented that way - so we've already paid the cost; thus C++ doesn't ever make the derived class non-virtual, since you can't save anything that way.)

Of course, multiple inheritance complicates things, but the basic principle is the same: inheriting from boost::noncopyable publically, protected-ly or privately, or including a member of type boost::noncopyable, makes the class non-copyable, and incurs no overhead, unless you confuse yourself and explicitly add some. :)

Writing a *non*-virtual, empty destructor can't hurt, of course (because you still haven't added any virtual functionality, so you won't pay that overhead), but it's also useless: its effect is identical to what you'd get by not writing a destructor at all.
Quote:
Using it as a base rather than a member is considered idiomatic for some reason.


Probably to take advantage of the empty base optimisation. C++ compilers must give regular members different addresses AFAIK.
Inheritace makes more conceptual sense to me her than composition - I think it makes the code more self documenting.

This topic is closed to new replies.

Advertisement