我想知道是否可以让编译器为代码发出警告/错误,如下所示:
注意:
1.是的,这是糟糕的编程风格,我们应该避免这种情况 - 但我们正在处理遗留代码,并希望编译器可以帮助我们识别这些情况.)
2.我更喜欢编译器选项(VC++)来禁用或启用对象切片(如果有的话).
class Base{}; class Derived: public Base{}; void Func(Base) { } //void Func(Derived) //{ // //} //main Func(Derived());
在这里,如果我注释掉第二个函数,第一个函数将被调用 - 而编译器(VC++和Gcc)对此感觉很舒服.
它是C++标准吗?并且我可以问编译器(VC++)在遇到这样的代码时给我一个警告吗?
非常感谢!!!
编辑:
非常感谢你的帮助!
我找不到一个编译器选项来给出错误/警告 - 我甚至在MSDN论坛上发布了这个VC++编译器顾问没有回答.所以我担心gcc和vc ++都没有实现这个功能.
因此,添加构造函数将派生类作为参数将是目前最好的解决方案.
编辑
我已经向MS提交了一个feedbak,希望他们能尽快修复它:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=421579
-Baiyan
如果你可以修改基类,你可以做类似的事情:
class Base { public: // not implemented will cause a link error Base(const Derived &d); const Base &operator=(const Derived &rhs); };
取决于您的编译器应该为您提供翻译单元,也可能是切片发生的功能.
作为Andrew Khosravian答案的变体,我建议使用模板化复制构造函数和赋值运算符.这样,您不需要知道给定基类的所有派生类,以保护该基类不被切片:
class Base { private: // To force a compile error for non-friends (thanks bk1e) // Not implemented, so will cause a link error for friends templateBase(T const& d); template 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 */ } };
虽然这减少了所需的工作量,但是通过这种方法,您仍然需要弄乱每个基类以保护它.此外,如果有合法的转换会造成问题,Base
对SomeOtherClass
雇用的operator Base()
成员SomeOtherClass
.(在这种情况下,boost::disable_if
可以使用更复杂的解决方案.)在任何情况下,一旦确定了对象切片的所有实例,就应该删除此代码.
对于世界的编译器实现者:测试对象切片绝对是值得创建(可选)警告的东西!我想不出一个需要行为的实例,并且它在新手C++代码中很常见.
[编辑27/3/2015:]正如Matt McNab所指出的,你实际上并不需要像我上面那样明确地声明复制构造函数和赋值运算符,因为它们仍然会被编译器隐式声明.在2003 C++标准中,在12.8/2下的脚注106中明确提到了这一点:
因为模板构造函数永远不是复制构造函数,所以这种模板的存在不会抑制复制构造函数的隐式声明.模板构造函数与其他构造函数(包括复制构造函数)一起参与重载解析,并且如果模板构造函数提供比其他构造函数更好的匹配,则可以使用模板构造函数来复制对象.