Given the following code:
#include <boost/noncopyable.hpp>
enum Error { ERR_OK=0 };
struct Filter : private boost::noncopyable
{
Filter() {}
virtual ~Filter() {}
virtual int filter(int* data) const = 0;
};
struct SpecialFilter : public Filter, private boost::noncopyable
{
inline SpecialFilter(unsigned int min, unsigned int max) : min(min), max(max) {}
virtual ~SpecialFilter() {}
virtual int filter(int* data) const
{
// ...
return ERR_OK;
}
unsigned int min;
unsigned int max;
};
struct AClass
{
AClass() {}
AClass(const AClass& other) {}
~AClass() {}
int specialFilter(int channel, int minThreshold, int maxThreshold)
{
// ...
return filter(channel, SpecialFilter(123, 321));
}
int filter(int channel, const Filter& filter)
{
// ...
return ERR_OK;
}
};
My compiler (GCC 4.2) complains:
- warning: direct base ‘boost::noncopyable_::noncopyable’ inaccessible in ‘SpecialFilter’ due to ambiguity
- noncopyable.hpp: In copy constructor ‘Filter::Filter(const Filter&)’:
- noncopyable.hpp:27: error: ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’ is private
- synthezised method first required here: [return filter(channel, SpecialFilter(123, 321));]
But I don't call the copy constructor!
The reason the copy constructor is not called is because the copy constructor itself is a function with one parameter. You didn't call such function,so it didn't execute.
In Java it simply copies the reference. The object's state is not copied so implicitly calling the copy constructor makes no sense. And that's all there is to it really.
The compiler also creates a copy constructor if we don't write our own copy constructor. Unlike the default constructor, the body of the copy constructor created by the compiler is not empty, it copies all data members of the passed object to the object which is being created.
In C++, the compiler automatically generates the default constructor, copy constructor, copy-assignment operator, and destructor for a type if it does not declare its own. These functions are known as the special member functions, and they are what make simple user-defined types in C++ behave like structures do in C.
You never call copy constructor. The copy constructor is always called for you implicitly by the compiler. So you need to learn to recognize situations when it might be called.
When you attach a const reference to a temporary object
...
return filter(channel, SpecialFilter(123, 321));
...
the compiler has the right to perform a copy of the temporary object and require an accessible copy constructor (even if it won't be actually called). This is what is causing the problem in your case.
In other words, when you make some type non-copyable, you also give up the possibility to attach const references to temporary objects of that type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With