是否可以使用关键字explicit来防止方法参数的自动转换? 我知道你可以用C++关键字“显式”来构造类的构造函数,以防止类型的自动转换。可以使用相同的命令来防止类方法的参数转换吗

是否可以使用关键字explicit来防止方法参数的自动转换? 我知道你可以用C++关键字“显式”来构造类的构造函数,以防止类型的自动转换。可以使用相同的命令来防止类方法的参数转换吗,c++,implicit-conversion,explicit,C++,Implicit Conversion,Explicit,我有两个类成员,一个接受bool作为参数,另一个接受无符号int。当我用int调用函数时,编译器将参数转换为bool并调用了错误的方法。我知道最终我会替换bool,但现在我不想在开发这个新例程时破坏其他例程。编译器给出了“不明确调用”警告,这就足够了 我当时正在进行TDD开发,没有意识到我忘记在mock对象中实现相应的调用。您也可以编写一个int版本来调用bool对象。否。显式防止特定类之间的自动转换,而不考虑上下文。当然,您不能对内置类执行此操作。bool是一个int,限制为0或1。这就是返回

我有两个类成员,一个接受bool作为参数,另一个接受无符号int。当我用int调用函数时,编译器将参数转换为bool并调用了错误的方法。我知道最终我会替换bool,但现在我不想在开发这个新例程时破坏其他例程。

编译器给出了“不明确调用”警告,这就足够了


我当时正在进行TDD开发,没有意识到我忘记在mock对象中实现相应的调用。

您也可以编写一个int版本来调用bool对象。

否。
显式
防止特定类之间的自动转换,而不考虑上下文。当然,您不能对内置类执行此操作。

bool是一个int,限制为0或1。这就是返回0的全部概念;,这在逻辑上与说returnfalse相同;(但不要在代码中使用此选项)

不,不能使用显式,但可以使用模板化函数捕获错误的参数类型

使用C++11,可以将模板函数声明为
delete
d。下面是一个简单的例子:

#include <iostream>

struct Thing {
    void Foo(int value) {
        std::cout << "Foo: value" << std::endl;
    }

    template <typename T>
    void Foo(T value) = delete;
};

C++11之前的代码中,可以使用未定义的私有函数来实现

class ClassThatOnlyTakesBoolsAndUIntsAsArguments
{
public:
  // Assume definitions for these exist elsewhere
  void Method(bool arg1);
  void Method(unsigned int arg1);

  // Below just an example showing how to do the same thing with more arguments
  void MethodWithMoreParms(bool arg1, SomeType& arg2);
  void MethodWithMoreParms(unsigned int arg1, SomeType& arg2);

private:
  // You can leave these undefined
  template<typename T>
  void Method(T arg1);

  // Below just an example showing how to do the same thing with more arguments
  template<typename T>
  void MethodWithMoreParms(T arg1, SomeType& arg2);
};
仅访问工具和单元的类
{
公众:
//假设这些定义存在于其他地方
无效方法(布尔arg1);
void方法(无符号整数arg1);
//下面是一个示例,演示如何使用更多参数执行相同的操作
具有更多参数的void方法(布尔arg1、SomeType和arg2);
void MethodWithMoreParms(无符号int arg1,SomeType&arg2);
私人:
//您可以不定义这些
模板
无效法(T arg1);
//下面是一个示例,演示如何使用更多参数执行相同的操作
模板
具有更多参数的void方法(T arg1、SomeType和arg2);
};
缺点是,在这种情况下,代码和错误消息不太清楚,因此只要可用,就应该选择C++11选项

对每个采用
bool
unsigned int
的方法重复此模式。不要为方法的模板化版本提供实现

这将强制用户始终显式调用bool或unsigned int版本


任何尝试调用类型不是
bool
unsigned int
Method
,都将无法编译,因为成员是私有的,当然要遵守可见性规则的标准例外(朋友、内部调用等)。如果某个具有访问权限的对象调用私有方法,则会出现链接器错误。

可能适合您的方法是使用模板。下面显示了模板函数
foo()
专门用于
bool
unsigned int
int
main()
函数显示如何解析调用。请注意,使用未指定类型后缀的常量
int
的调用将解析为
foo()
,因此如果您不专门处理
int
,则调用
foo(1)
时会出错。如果是这种情况,则使用文字整型常量的调用方必须使用
“U”
后缀来获取要解析的调用(这可能是您想要的行为)

否则,在将其传递到
unsigned int
版本之前,您必须专门处理
int
,并使用
“U”
后缀或将其转换为
unsigned int
(或者,如果您需要,可以断言该值不是负值)

#包括
模板
void foo(T);
模板
void foo(bool x)
{
printf(“foo(bool)\n”);
}
模板
void foo(无符号整数x)
{
printf(“foo(unsigned int)\n”);
}
模板
void foo(int x)
{
printf(“foo(int)\n”);
}
int main()
{
傅(真);
傅(假),;
foo(静态_-cast(0));
foo(0U);
foo(1U);
foo(2U);
foo(0);
傅(1),;
富(2),;
}

以下是一个非常基本的包装器,可用于创建强typedef:

template <typename V, class D> 
class StrongType
{
public:
  inline explicit StrongType(V const &v)
  : m_v(v)
  {}

  inline operator V () const
  {
    return m_v;
  }

private:
  V m_v; // use V as "inner" type
};

class Tag1;
typedef StrongType<int, Tag1> Tag1Type;


void b1 (Tag1Type);

void b2 (int i)
{
  b1 (Tag1Type (i));
  b1 (i);                // Error
}
模板
类strong类型
{
公众:
内联显式strong类型(V常量和V)
:m_v(v)
{}
内联运算符V()常量
{
返回m_v;
}
私人:
V m_V;//使用V作为“内部”类型
};
Tag1类;
typedef strong类型tag1类型;
无效b1(Tag1型);
虚空b2(内部一)
{
b1(Tag1类型(i));
b1(i);//错误
}
这种方法的一个很好的特性是,您还可以区分具有相同类型的不同参数。例如,您可以拥有以下内容:

class WidthTag;
typedef StrongType<int, WidthTag> Width;  
class HeightTag;
typedef StrongType<int, HeightTag> Height;  

void foo (Width width, Height height);
类宽度标签;
typedef strong字体宽度;
类高度标签;
typedef strong字体高度;
void foo(宽、宽、高);
“foo”的客户端将很清楚哪个参数是哪个。

当前接受的(使用私有模板函数)很好,但已经过时。使用C++11,我们可以使用
delete
d函数:

#include <iostream>

struct Thing {
    void Foo(int value) {
        std::cout << "Foo: value" << std::endl;
    }

    template <typename T>
    void Foo(T value) = delete;
};

int main() {
    Thing t;
    int int_value = 1;
    size_t size_t_value = 2;

    t.Foo(int_value);

    // t.Foo(size_t_value);  // fails with below error
    // error: use of deleted function
    //   ‘void Thing::Foo(T) [with T = long unsigned int]’

    return 0;
}
#包括
结构物{
void Foo(int值){

std::cout投票赞成;这毕竟正确回答了问题。但这将禁用所有自动转换。是的,它将禁用所有自动转换。Dan希望“防止类方法的参数转换”有问题的方法,我们可以使用模板特化的方法,如果需要的话,我们可以把基本类型映射到特定的方法。我意识到这是一个古老的答案。有没有一种方法可以使用<代码>删除>代码>或其他一些现代C++特性来完成同样的事情,没有这个代码>私有< /代码> HKAIN。ss?编辑:啊哈!它很有效!是的,你可以
class WidthTag;
typedef StrongType<int, WidthTag> Width;  
class HeightTag;
typedef StrongType<int, HeightTag> Height;  

void foo (Width width, Height height);
#include <iostream>

struct Thing {
    void Foo(int value) {
        std::cout << "Foo: value" << std::endl;
    }

    template <typename T>
    void Foo(T value) = delete;
};

int main() {
    Thing t;
    int int_value = 1;
    size_t size_t_value = 2;

    t.Foo(int_value);

    // t.Foo(size_t_value);  // fails with below error
    // error: use of deleted function
    //   ‘void Thing::Foo(T) [with T = long unsigned int]’

    return 0;
}