【问题标题】:Converting pointer of class A to class B in function return, when B has constructor with `A*`在函数返回中将 A 类的指针转换为 B 类,当 B 具有带有 `A*` 的构造函数时
【发布时间】:2020-11-09 07:45:41
【问题描述】:

在 C++ 中,我们能否从一个函数返回一个 A 的指针,该函数的实际返回值是一个不同的结构 B,它确实将第一个对象作为 A 的指针?

考虑以下场景。

struct B {
    A* ptr;
    // code...

    B(A* _ptr)
    {
        // code...
    }

};

B foo()
{
    A* tmp;
    // code...
    return tmp;
}

B bar()
{
    A* tmp;
    // code...
    return B(tmp);
}

foo() 方法能正常工作吗?能不能调用构造函数?

或者foo()将无法调用构造函数,它只在B按以下方式定义的情况下起作用,

struct B {
    A* ptr;
    // code...

    B(A* _ptr) : ptr(_ptr)
    {
        // some code (doesn't changes `ptr`)
    }

};

按以下方式或

struct B {
    A* ptr; // NO more data elements other than `ptr`

    B (A* _ptr) : ptr(_ptr) {
        // some code (doesn't changes `ptr`)
    }
};

如果有效,是因为B 中的A* ptr 是第一个对象吗?

我想知道在不同的 C++ 版本(

我想,bar 是最好的写法。

【问题讨论】:

    标签: c++ constructor type-conversion implicit-conversion


    【解决方案1】:

    让我们测试一下吧!

    #include <iostream>
    
    struct A;
    
    struct B {
        B(A* _ptr)
        {
            std::cout << "I've been called!" << std::endl;
        }
    
    };
    
    B foo()
    {
        A* tmp;
        return tmp;
    }
    
    int main()
    {
        foo();
        return 0;
    }
    

    这样简单程序的输出是:

    I've been called!
    

    表示构造函数已被调用。

    这是可能的,因为B (A* _ptr) 是一个转换构造函数。这种类型的构造函数允许自动转换为正在构造的类。


    正如@john 提到的,要禁用此行为,我们使用explicit 说明符。

    explicit B(A*)foo() 不再被接受。


    此外,如您所见,在我的B 版本中,没有成员A* ptr; - 这不是必需的。

    【讨论】:

    • 为了公平测试,它只会回答一个特定编译器的问题。
    • 我不知道自动转换。当然,我在发布之前进行了测试,但我怀疑它是特定于编译器还是特定于 C++ 版本。至少我开始了解这个概念,而不仅仅是知道它是否有效。谢谢。
    • 也感谢您的补充评论。这真的很有帮助。
    【解决方案2】:

    更进一步的 Jorengarenar 所说的。有时您想禁用此行为。这就是 explicit 关键字的作用

    #include <iostream>
    
    struct A;
    
    struct B {
        explicit B(A* _ptr)
        {
            std::cout << "I've been called!" << std::endl;
        }
    
    };
    
    B foo()
    {
        A* tmp;
        return tmp;
    }
    
    int main()
    {
        foo();
        return 0;
    }
    

    此版本不再编译。 return tmp; 是一个错误,但 return B(tmp); 会编译并调用构造函数。

    【讨论】:

    • 哦,我明白了。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    相关资源
    最近更新 更多