【问题标题】:c++ explicit contructor not blocking double to int convertionc++ 显式构造函数不阻止 double 到 int 的转换
【发布时间】:2020-02-12 17:08:15
【问题描述】:

我有一个来自 int 的 C 类的构造函数和一个来自 double 的构造函数。

我让第一个进行隐式类型转换,但使用关键字显式阻止第二个。

但是,不幸的是,出现了一个 double 到 int 的隐式转换.. 我可以以某种方式阻止它吗?

这是一个简化的例子

//g++  5.4.0
#include <iostream>
using namespace std;

class C{
    int* tab;
    public:
    C():tab(nullptr){ cout<<"(void)create zilch\n"; }
    C(int size):tab(new int[size]){ cout<<"(int)create " << size << "\n"; }
    explicit C(double size):tab(new int[(int)size]){ cout<<"(double)create " << size << "\n"; }
    ~C(){ if(tab) {cout<<"destroy\n"; delete[] tab;} else cout <<"destroy zilch\n"; }
};    

int main()
{
    cout << "start\n";
    {
        C o1(1);
        C o2 = 2; //ok, implicit conversion allowed
        C o3(3.0);
        C o4 = 4.0; //ko, implicit conversion to double blocked... but goes to int 
    }
    cout << "stop\n";
}

//trace 
//
//start
//(int)create 1
//(int)create 2
//(double)create 3
//(int)create 4
//destroy
//destroy
//destroy
//destroy
//stop

【问题讨论】:

  • 无关,但很重要:永远不要在 C++ 中使用 new 和 delete。它们是低级操作。在您的示例中,使用std::vector&lt;int&gt;。
  • 您至少收到编译器警告吗?
  • @Mikhail C++ 可以是一种低级语言。最好说一个人不应该使用它们。新的和删除的仍然很重要。
  • 欺骗是关于如何以一种有效的方式防止转换。但是,如果您的问题实际上是关于为什么您的方式不起作用,那就说吧。该问题可以重新打开
  • 我的评论只是一个评论,只是对您要查找的内容的有根据的猜测。但是,它确实有一些警告,因为它是一把大锤子,并且可能会导致问题(除非您对自己的类型很迂腐)。我现在没有时间做一个你可以接受的正确答案。很快有人可能会提供一个全面而解释性的答案。

标签: c++ explicit


【解决方案1】:

您可以尝试将 C(int) 构造函数替换为使用启用类型特征的构造函数,例如

#include <iostream>
#include <type_traits>
using namespace std;

class C{
    int* tab;
    public:
    C():tab(nullptr){ cout<<"(void)create zilch\n"; }
    template<typename I, typename = typename enable_if<is_integral<I>::value>::type>
    C(I size):tab(new int[size]){ cout<<"(int)create " << size << "\n"; }
    explicit C(double size):tab(new int[(int)size]){ cout<<"(double)create " << size << "\n"; }
    ~C(){ if(tab) {cout<<"destroy\n"; delete[] tab;} else cout <<"destroy zilch\n"; }
};

int main()
{
    cout << "start\n";
    {
        C o1(1);
        C o2 = 2; //ok, implicit conversion allowed
        C o3(3.0);
        C o4 = 4.0; //ko, implicit conversion to double blocked... but goes to int
    }
    cout << "stop\n";
}

这会给你一个像这样的错误:

test.cpp: In function ‘int main()’:
test.cpp:22:16: error: conversion from ‘double’ to non-scalar type ‘C’ requested
         C o4 = 4.0; //ko, implicit conversion to double blocked... but goes to int
                ^

【讨论】:

  • 一种优雅的方法。请注意,它也会接受一个字符:C c = 'c'。您可以将is_integral&lt;I&gt; 更改为is_same&lt;I, int&gt;。
【解决方案2】:

好吧! Eljay 在 cmets 中得到了更快的速度,但这是最终代码,在尝试隐式使用 double 时会出现编译错误

#include <iostream>
using namespace std;

class C{
    int* tab;

public:
    //THE TRICK: block any implicit conversion by default
    template <class T> C(T) = delete;

    C():tab(nullptr){ cout<<"(void)create zilch\n"; }
    C(int size):tab(new int[size]){ cout<<"(int)create " << size << "\n"; }
    explicit C(double size):tab(new int[(int)size]){ cout<<"(double)create " << size << "\n"; }
    ~C(){ if(tab) {cout<<"destroy\n"; delete[] tab;} else cout <<"destroy zilch\n"; }
};

int main()
{
    cout << "start\n";
    {
        C o1(1);
        C o2 = 2; //ok, implicit conversion allowed
        C o3(3.0);
        C o4 = 4.0; //ko, implicit conversion to other types deleted
        C o5 = (C)5.0; //ok. explicit conversion
    }
    cout << "stop\n";
}

【讨论】:

  • 请注意,这也会阻止复制和移动构造函数,因此请务必手动执行这些操作:(
  • @Mooing Duck 实际上不是。无需进一步工作即可使用这些构造函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 2018-05-30
相关资源
最近更新 更多