How to generate a compiler warning/error when obje

2019-03-12 11:53发布

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

8条回答
小情绪 Triste *
2楼-- · 2019-03-12 12:38
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.

查看更多
倾城 Initia
3楼-- · 2019-03-12 12:39

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.

查看更多
登录 后发表回答