How to generate a compiler warning/error when object sliced

后端 未结 8 1561
执笔经年
执笔经年 2021-02-04 03:58

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

8条回答
  •  伪装坚强ぢ
    2021-02-04 04:03

    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.

提交回复
热议问题