This might be a silly question, but...
I've been writing a number of classes that utilize non-copyable members. These classes are never initialized via the copy constructor in my source. When I try to compile without supplying my own copy-constructor, g++ throws out many errors about how it can't build a default copy constructor, due to the non-copyable member objects.
Is there a way to tell the compiler to just not give me a copy constructor?
EDIT: Yeah... feels silly... I had a case where I was invoking the copy-constructor by accident in a boost::bind call. Lesson learned.
The usual way to make things noncopyable is to declare but not define a copy constructor, and make it private so nothing can call it.
The next revision of the language will provide an explicit way to suppress these generated functions.
If you don't actually cause the copy-constructor to be called then it is not an error if the compiler would be unable to generate one. It sounds like you are (possibly indirectly) causing the copy-constructor to be used.
You can suppress the compiler generated one by declaring your own copy-constructor (you don't need to define it if you're not using it). You can place it in the private section of your class.
If this changes the error to say that the copy-constructor is inaccessible or you get link errors then you really are causing the copy-construtor to be used and you need to analyze why this is.
Not in the current version of C++. In C++ 0x, there will be an =delete; syntax to tell it that you don't want one of the special member functions the compiler will generate by default if you don't defined one yourself.
Until the new C++ 0x standard is fully supported, the best you can do is to delclare a version of the special member function, but not implement them. Normally they are made private (to help make it clear that they shouldn't be used).
Class foo
{
// ... rest of definition
private:
foo (const foo& rhs); // Do Not Implement
const foo& operator= (const foo& rhs); // Do Not Implement
};
No :)
If you want your class to be non-copyable use something like boost::noncopyable
class MyClass : private boost::noncopyable
{
}
or use a parametrizied macro in your class definition that declares a private copy constructor.
Related
I read this question, but it still doesn't make a lot of sense to me. It still sounds more like a sugarcoating feature.
What's the difference between:
class A
{
// public/private ?
A (const A&) = delete;
};
and
class A
{
private:
A (const A&); // MISSING implementation
};
Same for operator= or other functions.
One difference is that =delete allows for compile-time errors while in some cases the declaration without a definition is only caught at link-time (at which the error message is typically not pointing you to the source of the problem). One such case is when you add a member function that tries to copy an instance of A. Even when it's not a member function of A, the error message about the copy-ctor being private is not as clear as using =delete.
To avoid confusion, I'd recommend you make the deleted function public as otherwise you will get additional and misleading error messages.
The difference is that the purpose of the =delete code is explicit in it's purpose. Declaring functions as private / inaccessible was a trick. Although most people knew it, the error it generated was obscure (a linking/access level error instead of a semantical problem in the code - i.e. "you are using a deleted function").
One difference is that the old-fashioned form gives undefined behaviour if the class (or a friend) tries to destroy itself. Within class members and friends, the destructor is accessible, so there is no compile-time error if it's used. Instead, you get a violation of the One Definition Rule. In practice, this will cause a link error, but formally the behaviour is undefined.
Deleting the constructor (or other function) causes a compile error if the function is needed in any circumstances; and states the intent more explicitly, allowing the compiler to give better diagnostic messages. This is especially useful when functions are implicitly deleted due to something else being deleted.
Another thing which hasn't been mentioned yet: when inheriting / overriding, you can't =delete a function which already has a body but you can change a public function into a private one, making it basically inaccessible from outside.
In "The C++ programming language", at page 265, the author makes the following statement:
Because of historical accident, the operators = (assignment), & (address-of), and , (sequencing;
§6.2.2) have predefined meanings when applied to class objects. These predefined meanings can
be made inaccessible to general users by making them private:
Then the following example is given:
class X {
private:
void operator=(const X&);
void operator&();
void operator,(const X&);
// ...
};
void f(X a, X b)
{
a = b; // error: operator= private
&a; // error: operator& private
a,b; // error: operator, private
}
I can't quite understand what do these "error" comments refer to? Does that mean I should not define a function like f, or that all of the =, &, and , operators should be used according to the default way, and it is not necessary to redefine them?
This example simply shows a way to prevent yourself or other developers of the code from using operators, which can be used without having been defined in the class, because they're automatically generated (and have default meanings for the operations they represent).
The author of the example meant, that if you try to assign b to a (in line a = b) it will cause an error, because the assignment operator is private in the class definition.
Similar error occurs in case of address-of in the second line, and the comma operator in the third.
Making default operators/constructors private if you know they're not supposed to be used (or haven't been implemented yet) is good, because one may accidentally use a very frequent operator like assignment or copy-constructor, being unaware that it's default behavior conflicts with the class lifecycle. If such operator or constructor is made private at the very beginning of class design, the compiler will generate a compile-time error instead of performing a potentially dangerous operation without notice if the programmer accidentally uses the method.
Think default assignment operator and member pointer: it will copy the pointer whereas you might want the object to be the owner of data. Then, after someone assigns one object to another without knowing that assignment is not implemented, you will end up with a double free error. Instead of that, if the operator is private, you'll get a nice error and the code will not even compile, and you'll know what's going on.
The author intends to point out here that the operators =, & and , are usually implicitly available for a class.
So if you don't want your objects to be operated on through them then you declare them as private thus disallowing their use.
Since they are declared as private you cannot access them anymore outside the class and the compiler gives you a compilation error. The function is an example showing that.
Providing your own implementation of any operator is basically the same as implementing a class method. Operators and methods are the same in terms of accessibility. What you do is disallowing access to operators from the caller's code.
It's absolutely the same as if you defined a private method and then tried to call it from some code that is not part of your class. Just make the operators public and errors will go away.
It basically prevents any one from making an 'X' object and using the "=", "&", and "," operators on that class. Because the author of the class may implement those objects with a meaning that is quite different to what the consumer of the class might think they do ... so its best to prevent them being used at all in the case of ambiguity.
The function f is an example of a user trying to use the private operators. It shows you what code it is that you're preventing by making them private. The comment // error means that a program that contained that line would fail to compile for the stated reason.
Before discussing the error, a key here is to understand that these operations will be implicitly made available for your class. This is the essence of Scott Meyers' advice "Know what functions C++ silently writes and calls."
C++ will automatically implement the assignment operator for your class, but it may not be done correctly (for example, if your class contains a pointer member variable). By defining the assignment operator explicitly, you are telling the compiler to use your implementation instead of generating one for you. And by making it private, you are essentially disallowing assignment of one class instance to another. Anywhere you try to do this in your code, the compiler will complain, which is a good thing if you really don't want assignment to be done.
In function f the author is showing you that these statements will not compile because of how the operators are defined in the class. It is perfectly acceptable to redefine operators for your class, and sometimes it is definitely required (for example, to implement a deep copy of a pointer member variable in your class). The point of the example is to show that a) you can provide your own implementation of these operators for your class, and b) because of this you have control over whether the operators are supported and implemented correctly for your class.
As far as I understand, C++ default copy constructor only behaves as expected when the class is a POD class.
I would like to know if there's a solution for preventing the programmer to write code which (implicitely or not) uses the default copy constructor if the object is not POD.
I know you can always make your copy and assignement private to solve this problem but I'd like to know if there's an automated solution. For example the compiler could generate a warning in case your code generates a default copy constructor call and your class is not POD ?
The goal here is to detect the cases where I forgot to declare copy/assignement private or to manually define them.
Also do you guys know if cppcheck can do that ?
In C++0x you can explicitly prevent use of special member functions like this:
struct NonCopyable {
NonCopyable & operator=(const NonCopyable&) = delete;
NonCopyable(const NonCopyable&) = delete;
NonCopyable() = default;
};
See here for more details. Still manual unfortunately, but more elegant than now.
The centralized way to disable default construction is to make the default constructor inaccessible.
You write: "I would like to know if there's a solution for preventing the programmer to write code which (implicitely or not) uses the default copy constructor if the object is not POD. ."
Presumably you mean you'd like the compiler to react to any default construction of any non-POD object.
Sorry, no compiler-independent way.
Reason: a great many non-POD classes, like smart pointers and containers such as std::vector, rely on default construction to be useful.
The g++ compiler has an option -Weffc++ to warn about violations of the guidelines in Scott Meyers’ Effective C++, but as far as I know – I could be wrong – this does not include your case. Can reportedly be useful, though.
Cheers & hth.,
No, since it is a language's requirement.
When creating a class, you have 3 possibilities: to have default copy ctor, to write your own or to disable it (with different ways to do it; inheriting from boost::noncopyable to mention one). Not that clear why compiler should warn you about choosing one of these.
To disallow copying or assigning a class it's common practice to make the copy constructor
and assignment operator private. Both Google and Qt have macros to make this easy and visible.
These macros are:
Google:
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
Qt:
#define Q_DISABLE_COPY(Class) \
Class(const Class &); \
Class &operator=(const Class &);
Questions:
Why are the signatures of the two assignment operators different? It seems like the Qt version is correct.
What is the practical difference between the two?
It doesn't matter. The return type is not part of a function's signature, as it does not participate in overload resolution. So when you attempt to perform an assignment, both declarations will match, regardless of whether you use the return type.
And since the entire point in these macros is that the functions will never get called, it doesn't matter that one returns void.
I'd just like to mention that there is an alternative strategy for implementing an abstraction for disallowing copy and assignment of a class. The idea is to use inheritance instead of the preprocessor. I personally prefer this approach as I follow the rule of thumb that it is best to avoid using the preprocessor when at all possible.
boost::noncopyable is an example implementation. It is used as follows:
class A : noncopyable
{
...
};
See Boost.Utility, specifically boost::noncopyable. It's not a macro but a base class with private copy and assignment. It prevents the compiler from generating implicit copy and assignment in derived classes.
edit: Sorry, this was not an answer to the original question. By the way, boost::noncopyable uses a const reference as return type for the assignment operator. I was under the impression that the type of the return value doesn't matter since it's not supposed to be used. Still, making the operator private doesn't prevent usage inside the class or friends in which case a non-usual return type (like void, a const reference, etc) might lead to compilation errors and catch additional bugs.
There's no practical difference. The assignment operator signatures differ just as a matter of style. It's usual to have an assignment operator returning a reference to allow chaining:
a = b = c;
but a version returning void is also legal and will work just fine for cases when the only purpose is to just declare the operator private and therefore prohibited to use.
From the standard, 12.8, clause 9: "A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X&, or const volatile X&." It says nothing about the return type, so any return type is permissible.
Clause 10 says "If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly."
Therefore, declaring any X::operator=(const X&) (or any other of the specified assignment types) is sufficient. Neither the body nor the return type is significant if the operator will never be used.
Therefore, it's a stylistic difference, with one macro doing what we'd likely expect and one saving a few characters and doing the job in a way that's likely to surprise some people. I think the Qt macro is better stylistically. Since we're talking macro, we're not talking about the programmer having to type anything extra, and failing to surprise people is a good thing in a language construct.
Others have already answered why it's legal to have different return values for operator=; IMHO jalf said it best.
However, you might wonder why Google uses a different return type, and I suspect it's this:
You don't have to repeat the type name when disabling the assignment operator like this. Usually the type name is the longest part of the declaration.
Of course, this reason is void given that a macro is used but still - old habits die hard. :-)
Both serve the same purpose
Once you write this one:
Class &operator=(const Class &);
you will get the benefits of chain assignments. But in this case you want the assignment operator to be private. so it doesn't matter.
Qt version is backward compatible, while google's is not.
If you develop your library and deprecate the use of assignment before you completely remove it, in Qt it will most likely retain the signature it originally had. In this case older application will continue to run with new version of library (however, they won't compile with the newer version).
Google's macro doesn't have such a property.
As several other answers have mentioned, the return type of the function doesn't participate in the function signature, so both declarations are equivalent as far as making the assignment operator unusable by clients of the class.
Personally I prefer the idiom of having a class privately inherit from an empty non-copyable base class (like boost::noncopyable, but I have my own so I can use it in projects that don't have boost available). The empty base class optimization takes care of making sure there's zero overhead, and it's simple, readable, and doesn't rely on the dreaded preprocessor macro functionality.
It also has the advantage that copy and assignment can't even be used within class implementation code - it'll fail at compile time while these macros will fail at link time (likely with a less informative error message).
Incidentally, if you have access to the Boost libraries (You don't? Why the heck not??), The Utility library has had the noncopyable class for a long time:
class YourNonCopyableClass : boost::noncopyable {
Clearer IMHO.
In practice I would say that both should not be used anymore if you have a C++11 compiler.
You should instead use the delete feature , see here
Meaning of = delete after function declaration
and here
http://www.stroustrup.com/C++11FAQ.html#default
Why : essentially because compiler message is much more clearer. When the compiler need one of the copy or copy assignment operator, it immediately points out to the line where the =delete was coded.
Better and complete explanations can also be found in Item 11: Prefer deleted functions to private undefined ones from Effective Modern C++ book by Scott Meyers
I want to know if it is possible to let compiler issue a warning/error for code as following:
Note:
1. Yea, it is bad programming style and we should avoid such cases - but we are dealing with legacy code and hope compiler can help identify such cases for us.)
2. I prefer a compiler option (VC++) to disable or enable object slicing, if there is any.
class Base{};
class Derived: public Base{};
void Func(Base)
{
}
//void Func(Derived)
//{
//
//}
//main
Func(Derived());
Here if I comment out the second function, the first function would be called - and the compiler (both VC++ and Gcc) feels comfortable with that.
Is it C++ standard? and can I ask compiler (VC++) to give me a warning when met such code?
Thanks so much!!!
Edit:
Thanks all so much for your help!
I can't find a compiler option to give a error/warning - I even posted this in MSDN forum for VC++ compiler consultant with no answer. So I am afraid neither gcc nor vc++ implemented this feature.
So add constructor which take derived classes as paramter would be the best solution for now.
Edit
I have submit a feedbak to MS and hope they will fix it soon:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=421579
-Baiyan
If you can modify the base class you could do something like:
class Base
{
public:
// not implemented will cause a link error
Base(const Derived &d);
const Base &operator=(const Derived &rhs);
};
Depending on your compiler that should get you the translation unit, and maybe the function where the slicing is happening.
As a variation of Andrew Khosravian's answer, I'll suggest using templated copy constructors and assignment operators. This way you don't need to know all the derived classes of a given base class in order to safeguard that base class against slicing:
class Base
{
private: // To force a compile error for non-friends (thanks bk1e)
// Not implemented, so will cause a link error for friends
template<typename T> Base(T const& d);
template<typename T> Base const& operator=(T const& rhs);
public:
// You now need to provide a copy ctor and assignment operator for Base
Base(Base const& d) { /* Initialise *this from d */ }
Base const& operator=(Base const& rhs) { /* Copy d to *this */ }
};
Although this reduces the amount of work needed, with this approach you still need to mess with each base class in order to safeguard it. Also, it will cause problems if there are legitimate conversions from Base to SomeOtherClass that employ an operator Base() member of SomeOtherClass. (In that case, a more elaborate solution involving boost::disable_if<is_same<T, SomeOtherClass> > can be used.) In any case, you should remove this code once you've identified all instances of object slicing.
To the compiler implementors of the world: Testing for object slicing is definitely something that would be worthwhile creating (optional) warnings for! I can't think of one instance where it would be desired behaviour, and it's very commonly seen in newbie C++ code.
[EDIT 27/3/2015:] As pointed out by Matt McNab, you actually don't need to declare the copy constructor and assignment operator explicitly as I've done above, as they will still be implicitly declared by the compiler. In the 2003 C++ standard, this is explicitly mentioned in footnote 106 under 12.8/2:
Because a template constructor is never a copy constructor, the presence of such a template does not suppress the implicit declaration of a copy constructor. Template constructors participate in overload resolution with other constructors, including copy constructors, and a template constructor may be used to copy an object if it provides a better match than other constructors.
I would suggest adding a constructor to your base class which takes a const reference to the derived class explicitly (with a forward declaration). In my simple test app, this constructor gets called in the slicing case. You could then at least get a run-time assertion, and you could probably get a compile-time assertion with clever use of templates (eg: instantiate a template in a way which generates a compile-time assertion in that constructor). There may also be compiler-specific ways to get compile time warnings or errors when you call explicit functions; for example, you can use "__declspec(deprecated)" for the "slice constructor" in Visual Studio to get a compile-time warning, at least in the function-call case.
So in your example, the code would look like this (for Visual Studio):
class Base { ...
__declspec(deprecated) Base( const Derived& oOther )
{
// Static assert here if possible...
}
...
This works in my test (compile-time warning). Note that it doesn't solve the copy case, but a similarly-constructed assignment operator should do the trick there.
Hope this helps. :)
The best way to combat this problem is usually to follow Scott Meyer's recommendation (see Effective C++) of only having concrete classes at the leaf nodes of your inheritance tree and ensuring that non-leaf classes are abstract by having at least one pure virtual function (the destructor, if nothing else).
It is surprising how often this approach helps clarify the design in other ways, as well. The effort of isolating a common abstract interface is usually a worthwhile design effort in any case.
Edit
Although I originally didn't make this clear, my answer comes from the fact that it is not possible to warn accurately about object slicing at compile time and for this reason it can lead to a false sense of security if you have a compile time assertion, or a compiler warning enabled. If you need to find out about instances of object slicing and need to correct them then it implies that you have the desire and ability to change the legacy code. If this is the case, then I believe that you should seriously consider refactoring the class hierarchy as a way of making the code more robust.
My reasoning is this.
Consider some library code that defines a class Concrete1 and uses it in the inferface to this function.
void do_something( const Concrete1& c );
Passing the type be reference is for efficiency and is, in general, a good idea. If the library considers Concrete1 to be a value type the implementation may decided to make a copy of the input parameter.
void do_something( const Concrete1& c )
{
// ...
some_storage.push_back( c );
// ...
}
If the object type of the passed reference is, indeed, Concrete1 and not some other derived type then this code is fine, no slicing is performed. A general warning on this push_back function invocation might produce only false positives and would most likely be unhelpful.
Consider some client code that derives Concrete2 from Concrete1 and passes it into another function.
void do_something_else( const Concrete1& c );
Because the parameter is taken by reference no slicing occurs here on the parameter to check, so it would not be correct to warn here of slicing as it may be that no slicing occurs. Passing in a derived type to a function that takes a reference or pointer is a common and useful way to take advantage of polymorphic types so warning or disallowing this would seem counter-productive.
So where is there error? Well the 'mistake' is passing in a reference to something that is derived from a class that is then treated as though it is a value type by the called function.
There is, in general, no way to generate a consistently useful compile time warning against object slicing and this is why the best defence, where possible, is to eliminate the problem by design.
This is commonly called Object Slicing and is a well-known enough problem to have its own Wikipedia article (although it is only a short description of the problem).
I believe I have used a compiler that had a warning you could enable to detect and warn about this. However, I don't recall which one that was.
Not really a solution to your immediate problem, but....
Most functions that take class/struct objects as parameters should declare the parameters to be of type "const X&" or "X&", unless they have a very good reason not to.
If you always do this, object slicing will never be a problem (references don't get sliced!).
class Derived: public Base{};
You're saying Derived IS a Base, and so it should work in any function that takes a base. If this is a real problem, maybe inheritance isn't what you really want to be using.
I modified your code slightly:
class Base{
public:
Base() {}
explicit Base(const Base &) {}
};
class Derived: public Base {};
void Func(Base)
{
}
//void Func(Derived)
//{
//
//}
//main
int main() {
Func(Derived());
}
The explicit keyword will make sure that the constructor will not be used as an implicit conversion operator - you have to call it explicitly when you want to use it.