9

我们使用的外部库包含以下显式构造函数:

class Chart {
public:
    explicit Chart(Chart::Type type, Object *parent);
    // ...
};

编译器抱怨以下警告:

chart.h: warning #2305: declaration of 'explicit' constructor
without a single argument is redundant

仅删除explicitchart.h 中的关键字而不重新编译库以避免警告是否是二进制兼容的?我的感觉是它是安全的,因为explicit无论如何在这种情况下没有意义。任何人都可以确认吗?

4

2 回答 2

9

如果你明白我的意思,你最好的选择是在包含期间关闭该警告。不要破解供应商代码。

从 C++11 开始,使用explicit多参数构造函数非常有意义,因为它可用于停止隐式大括号初始化。此外,标准并没有说删除explicit必须保留类的布局,因此您必须假设删除explicit 可能会破坏二进制兼容性。此外,删除它可能会改变人为的 SFINAE 模式的行为,因为该构造函数在某些情况下可能会重新可用。请参阅http://en.cppreference.com/w/cpp/language/sfinae

于 2016-09-14T08:09:35.033 回答
2

explicit在 C++11 及更高版本的大括号初始化器上下文中使用多个参数是有意义的:

void foo(Chart const &);

// ...

// Will only compile without `explicit`
foo({Chart::Type::pie, myObj});

删除它是否与二进制兼容explicit最终取决于您的编译器,因此您必须在其文档中找到它。

但是,由于explicit它是一种高级语言功能,它只能引导重载解析,所以我不希望它破坏兼容性,只要它不改变某些预先存在的调用的最佳匹配,包括在任何代码中您从库本身(模板和/或内联函数)编译

也就是说,这是纯粹的临时补丁:根据标准,这样做会让你直接进入 UB 领域。引用nm的评论:

摆弄这样的标题会破坏 ODR。供应商的二进制文件是使用某个类的特定定义编译的,您的二进制文件是使用同一类的不同定义编译的。那是违法的。变化多小并不重要。定义必须逐个令牌相同,句号。

我建议简单地将这些标头中的警告静音,方法是将它们包装在包含的#pragmas 中(或自定义代理标头中,并包含它)。

于 2016-09-14T08:12:57.563 回答