【问题标题】:Implicit casting C++隐式转换 C++
【发布时间】:2015-07-06 01:48:54
【问题描述】:

考虑这种情况:

ClassA obA;
ClassB obB;

obA = obB;

是不是,如果ClassA有一个参数为ClassB类型的构造函数,在这种情况下会被调用?

如果ClassB 中有一个重载的转换运算符 - 将ClassB 对象转换为ClassA 对象,则将调用运算符方法。如果有对应的构造函数和重载的强制转换运算符,会调用哪一个?我在哪里可以阅读它?

【问题讨论】:

标签: c++ implicit-conversion


【解决方案1】:

是不是,如果ClassA有一个参数为ClassB类型的构造函数,在这种情况下会被调用?

是的,构造函数被考虑用于隐式类型转换:

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

签名为ClassA::ClassA(ClassB) 的构造函数称为converting-constructor。在诸如赋值之类的函数调用期间,构造函数和用户定义的转换运算符被编译成一个重载集,并选择最佳的一个进行转换。

如果选择构造函数:如果源类型是按值类型,它会创建源类型 (ClassA) 的类型的纯右值,并使用目标类型 (ClassB) 的类型进行初始化,那是用来初始化参数的。如果源类型是引用,则使用reference-initialization rules


赋值运算符在ClassA 中隐式生成(假设它们没有被覆盖)。它们是:

ClassA& operator=(ClassA const&);
ClassA& operator=(ClassA      &&);

隐式转换序列可以选择构造函数或转换函数从ClassB -> ClassA const&ClassB -> ClassA&& 转换。

但是,在这种情况下,按照您的方案,转换将无法成功,因为它会模棱两可。考虑:

struct B { operator struct A(); };

struct A {
    A() = default;
    A(B) {}
};

B::operator A() { return A(); }

int main() 
{
    A a; B b;
    a = b; // Error! Ambiguous conversion
}

A::A(B)B::operator A() 都是用于转换的可行转换函数。因此,转换是模棱两可的,我们得到一个编译错误。

用户定义的转换仅适用于明确的情况(10.2、12.3.2)。

如果我们将A 类中的转换构造函数的签名更改为A::A(B const&),那么将使用B 中的转换运算符,因为A 的构造函数需要资格转换(添加const)。

cppreference 上有一个帖子,您可以在那里了解更多信息。

【讨论】:

    【解决方案2】:

    这段代码:

    ClassA obA;
    ClassB obB;
    
    obA = obB;
    

    不是你想的那样(*)。这段代码:

    ClassB obB;
    ClassA  obA = obB;
    

    在以下情况下将起作用(如提供的那样):

    1. ClassA 有构造函数,接受ClassB 作为参数:

    class ClassA
    {
    public:
        ClassA(const ClassB& b)
        {
            //construct *this from b
        }
    };
    

    2. ClassB 定义了转换类型操作符:

    class ClassB
    {
    public:
        operator ClassA() const
        {
            //construct ClassA from *this
        }
    };
    

    如果 ClassA 中有一个重载的强制转换运算符,其参数类型为 ClassB [...]。

    您的意思是 constructor,而不是 casting operator,对吗?您尝试将ClassA 转换为ClassB,因此ClassA 的转换运算符在这种情况下无关紧要。


    (*)obA 的构造之后,您将obB 分配给obA,因此在您的情况下,只有第二点适用。您还可以通过添加赋值运算符使其工作:

    3.

    class ClassA
    {
    public:
        ClassA& operator=(const ClassB& b)
        {
            //assign b to *this
        }
    };
    

    在你的情况下会被调用。

    【讨论】:

    • 关于#1 的好电话。值得注意的是,如果有人同时尝试 #1 和 #2,那么他们会遇到循环引用问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 2017-04-11
    • 2015-08-12
    • 2010-12-12
    • 1970-01-01
    相关资源
    最近更新 更多