简体   繁体   中英

How does boost::noncopyable work

I've stumbled upon 2 stupid questions during my C++ practixe :

  1. AFAIK in c++ copy constructor and assignment operators are not inherited...so how does boost::noncopyable help in this case to prohibit this stuff?

    \nclass X: private boost::noncopyable \n{ \n}; \n
    Is it necessary to use only private inheritance to achieve the goal?

  2. Is there only 1 way to declare assignment operator

    \nMyClass& operator= ( const MyClass & ); \n
    Is it the same thing to declare
    \nvoid operator= ( const MyClass & );  
    or
    \nconst MyClass& operator= ( const MyClass & );  
    ?

You are correct that the copy constructor and copy assignment operator are not inherited. Fortunately we do not need them inherited in order for this to work. If you inherit from a class that cannot be copied then that derived class cannot be copied as well as it cannot call the base class copy constructor in it's copy constructor.

Essential you inherit from a class that looks like

struct NonCopyable {
    NonCopyable & operator=(const NonCopyable&) = delete;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable() = default;
};

Which is enough to stop the compiler generated copy and assignment in the derived class from working. You can provide your own and override this but then that is defeating the point.

The non-copyable in C++11 and later will work by declaring it =delete , preferably public. However, before C++11 this was not possible and the combination of 2 techniques are being used:

  • Declare the method private
  • Don't implement the method

By making the method private, this cannot be called by non-friend classes. As a result, any code trying to call this will result in a compilation error.

In practice, the class can still copy itself. Therefore this method does not get implemented and you will get a linker error.

Inheriting from boost::noncopyable will prevent the second use case, however, it also prevents that the compiler can generate a valid default copy constructor ... as they will violate the previous constraints.

Note that if you really want, you can write copy constructors for the inheriting class by calling the normal constructors of these 'non-copyable' classes.

For your second question: Yes, you can give it whatever return type you want, though you can't write a = b = c; anymore.

1) When an object is constructed, all of the member objects and base objects must also be constructed. Since noncopyable::noncopyable(const noncopyable &) is private, noncopyable can never be copy-constructed. Therefore, any object that contains it as a member or base can also never be copy-constructed.

2) You may declare you assignment operator any of the three ways you've described. No, they are not "the same thing". One returns a mutable reference, one returns a const reference, and one returns void. The difference will be apparent if you ever try to operate on the result of the assignment operator. Consider this program fragment:

a = b;
(a = b).foo()

The first line will operate the same with any of your assignment operators. The second line will vary according to which assignment operator you use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM