gpt4 book ai didi

c++ - 如何确保显式构造函数被调用并允许大括号初始化?

转载 作者:行者123 更新时间:2023-11-28 04:02:09 24 4
gpt4 key购买 nike

考虑下面的基本程序。它具有 typedef int Number,目的是允许 future 的开发人员将其更改为当时最有意义的任何精度(或者甚至,比如说,使用 CGAL 的数字类型之一)。

可以看到一个Point被描述为一对Number,一个LineSegment被两个Point描述

我想完成两个目标:

  1. 如果用户试图用Number 以外的任何东西实例化Point,它应该触发编译时警告。我认为这就是 explicit 关键字的作用。相反,正如您在 p3 的实例化中看到的那样,我们默默地允许将 float 转换为 int
  2. 如果用户想用常量值初始化 LineSegment,只要这些值为 Number 就应该可行。

我的问题:

  1. 我是否误解了 explicit 应该如何使用?
  2. 期望编译器捕捉到这个是不可行的吗?换句话说,它是否需要在运行时的编程逻辑中?
typedef int Number;

class Point
{
public:
explicit Point(Number n1, Number n2)
: x(n1), y(n2)
{}

Number x;
Number y;
};

class LineSegment
{
public:
LineSegment(Point p1, Point p2)
: start(p1), end(p2)
{}

Point start;
Point end;
};

int main()
{
// Works as expected
Point p1(10, 10);
Point p2(20, 20);
LineSegment s1(p1, p2);

// How can I trigger a compiler error here?
Point p3(10.5, 11.5);

// Why can't a do the following?
//LineSegment s2({30, 30}, {40, 40});

return 0;
}

最佳答案

是的,你误会了explicit . explicit在构造函数上阻止构造函数被使用,例如当将某些内容传递给期望您的类类型作为参数的函数时,作为隐式用户定义的转换。 explicit的使用在你的构造函数上实际上是在阻止 LineSegment s2({30, 30}, {40, 40});出于这个确切原因进行编译,正如@JohannesSchaub 在问题评论中指出的那样。

explicit不会阻止构造函数自身参数中的隐式转换。

使用括号初始化语法时无法避免隐式转换,但可以通过将构造函数作为模板函数并检查其模板参数类型来获取实际传递的类型:

template<typename T1, typename T2>
Point(T1 n1, T2 n2)
: x(n1), y(n2)
{
static_assert(std::is_same_v<T1,Number> && std::is_same_v<T2,Number>
, "Construct Point with Number arguments!");
}

需要 #include<type_traits>对于 std::is_same_v和 C++17。 (在 C++17 之前,您需要使用 std::is_same<...>::value 。)

或者您可以使用 std::enable_if而不是 static_assert ,如果您不希望使用错误的类型导致硬错误。

关于c++ - 如何确保显式构造函数被调用并允许大括号初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59327320/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com