4

是否可以在 C++ 中覆盖(C 风格)强制转换?

假设我有代码

double x = 42;
int k = (int)x;

我可以让第二行中的演员执行我写的一些代码吗?就像是

// I don't know C++
// I have no idea if this has more syntax errors than words
operator (int)(double) {
    std::cout << "casting from double to int" << std::endl;
}

我问的原因是因为“有什么方法可以让 gcc 或 clang 对显式强制转换发出警告吗?” 和我的建议。

4

4 回答 4

5

§ 12.3.1/1 “类对象的类型转换可以由构造函数和转换函数指定。这些转换称为用户定义的转换,用于隐式类型转换(第 4 条)、初始化(8.5)和显式类型转换(5.4、5.2.9)。”

是的,我们可以进行转换,但前提是一侧或两侧都是用户定义的类型,所以我们不能为doubleto进行转换int

struct demostruct {
    demostruct(int x) :data(x) {} //used for conversions from int to demostruct
    operator int() {return data;} //used for conversions from demostruct to int
    int data;
};

int main(int argc, char** argv) {
    demostruct ds = argc; //conversion from int to demostruct
    return ds; //conversion from demostruct to int
}

正如 Robᵩ 指出的那样,您可以将explicit关键字添加到任何一个转换函数中,这需要用户在代码中使用 a(demostruct)argc(int)dslike 显式转换它们,而不是让它们隐式转换。如果您在同一类型之间进行转换,通常最好使用一个或两个 as explicit,否则可能会出现编译错误。

于 2012-04-25T17:01:19.407 回答
4

是的,但仅适用于您自己的类型。看这个:

#include <iostream>
struct D {
  // "explicit" keyword requires C++11
  explicit operator int() { std::cout << __FUNCTION__ << "\n"; }
};

int main () {
  int i;
  D d;
  //i = d;
  i = (int)d;
}

所以,你不能创造double::operator int(),但你可以创造MyDouble::operator int()

于 2012-04-25T17:00:02.993 回答
3

您不能为内置类型重载运算符,但可以为用户定义类型编写转换运算符:

struct Double {
    double value;
    operator int() const {
        shenanigans();
        return value;
    }
};

由于您的问题源于需要在代码中找到显式转换,因此还要注意 C++ 具有显式转换运算符。这些不仅比 C 风格的演员表更清晰,而且非常易于搜索:

static_cast<T>(x)      // Cast based on static type conversion.
dynamic_cast<T>(x)     // Cast based on runtime type information.
const_cast<T>(x)       // Add or remove const or volatile qualification.
reinterpret_cast<T>(x) // Cast between unrelated pointer and integral types.
于 2012-04-25T16:59:22.077 回答
1

转换为其他类型是 C++ 中的可重载运算符(这里有一些示例),但这个事实对您没有帮助。

Stroustrup希望语言是可扩展的,但不是可变的。因此,重载运算符只会将操作扩展到新类型,但您无法重新定义任何旧类型会发生什么。

但是,为了避免荒谬,(仍然)不允许为内置类型的内置运算符提供新的含义。因此,该语言保持可扩展但不可变。

于 2012-04-25T16:58:13.007 回答