Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中的隐式构造函数参数转换+;11_C++_C++11_Types_Compiler Construction_Type Conversion - Fatal编程技术网

C++ C+中的隐式构造函数参数转换+;11

C++ C+中的隐式构造函数参数转换+;11,c++,c++11,types,compiler-construction,type-conversion,C++,C++11,Types,Compiler Construction,Type Conversion,让我们编写以下代码: class A{ public: A(int x){} }; class B{ public: B(A a){}; }; int main() { B b = 5; return 0; } 编译时,编译器会抱怨: /home/test/main.cpp:80: candidate constructor not viable: no known conversion from 'int' to 'A' for 1st argument 我不想创建B

让我们编写以下代码:

class A{
public:
  A(int x){}
};

class B{
public:
  B(A a){};
};


int main() {
  B b = 5;
  return 0;
}
编译时,编译器会抱怨:

/home/test/main.cpp:80: candidate constructor not viable: no known conversion from 'int' to 'A' for 1st argument
我不想创建
B(int)
构造函数-我希望编译器隐式地将这个
int
转换成
A
对象

编辑:

直接初始化的工作原理如下:

B b(5);

是否可以改用assignment运算符?

改用直接初始化:

B b(5);

您可以使用正在转换为
a
的转换构造函数

class B {
public:
    // It doesn't hurt to keep that one
    B(A a){};

    template<
        typename T
        , EnableIf<std::is_convertible<T, A>>...
    >
    B(T&& value)
    {
        // How to use the value
        A a = std::forward<T>(value);
    }
};

// Now B b = foo; is valid iff A a = foo; is, except for a few exceptions
B类{
公众:
//留着这个没什么坏处
B(A){};
模板<
类型名T
,如果。。。
>
B(T&值)
{
//如何使用该值
A=标准::正向(值);
}
};
//现在B=foo;当A=foo时有效;是的,除了少数例外
确保您了解
启用if
约束的目的。如果不使用它,您将面临严重的编译错误,甚至更糟:根本没有错误。你也应该仔细考虑是否从潜在的很多类型中制造<代码> B<代码>转换是完全值得的。隐式转换往往使程序更难理解,这可能会很快超过它们所带来的明显好处。

请澄清:

B b = 5;
“副本初始化”不是分配。(见附件)

在这种情况下,您要求编译器首先执行两个隐式的用户定义转换,即
int->A,A->B
,然后将临时
B
对象传递给
B
的复制构造函数。编译器可以省略临时对象,但从语义上讲,您仍然要求语言跨类型进行两次跳转

编程语言中的所有隐式行为本质上都是可怕的。为了一点语法糖,我们要求C++“做一些魔法让它工作”。意外的类型转换会破坏大型复杂程序。否则,每次编写新函数或新类时,您都必须担心它可能影响的所有其他类型和函数,其副作用会波及整个代码。 你真的想从
int
->
apple
->
horse
->
horse\u power
->
飞机

由于这个原因,C++只允许一个隐式用户定义转换:

12.3转换[class.conv]

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

4最多对单个值隐式应用一个用户定义的转换(构造函数或转换函数)。

您最好使用显式强制转换或“直接初始化”,这两种方法都可以让编译器和协作者清楚地知道您正试图做什么。传统的或新的统一初始化语法均可工作:

B b(5);
B b{5};
B b = {5};

不,您不能隐式地这样做。为什么我不能隐式地这样做?尝试从A添加赋值运算符,例如
B&operator=(常量A&A)
B&运算符=(A)?是的,我已经尝试过了,但仍然得到相同的错误。谢谢,它可以工作,但我很想使用assignment运算符-这有可能吗?cough
B(int)
constructor-抱歉;)cough@danilo2您的代码未使用赋值运算符。它使用的是复制初始化。@Angew那么是否可以创建一些
复制构造函数
,以使此代码按我所希望的方式工作?这非常令人伤心:(谢谢大家:(