在函数 return 中将 class A 的指针转换为 class B,当 B 具有带“A*”的构造函数时
Converting pointer of class A to class B in function return, when B has constructor with `A*`
在 C++ 中,我们可以 return 来自函数的 A
的指针,其实际 return 值是不同的结构 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++ 版本(<11、11、14、17)上有什么可能性,或者它是否也取决于我使用的编译器。
我想,bar
是最好的写法。
我们来测试一下!
#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)
是一个转换构造函数。这种类型的构造函数允许自动转换为正在构造的class。
正如@john 提到的,要禁用此行为,我们使用 explicit
说明符。
explicit B(A*)
和 foo()
不再被接受。
此外,如您所见,在我的 B
版本中,没有成员 A* ptr;
- 它不是必需的。
进一步了解 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);
会编译并调用构造函数。
在 C++ 中,我们可以 return 来自函数的 A
的指针,其实际 return 值是不同的结构 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++ 版本(<11、11、14、17)上有什么可能性,或者它是否也取决于我使用的编译器。
我想,bar
是最好的写法。
我们来测试一下!
#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)
是一个转换构造函数。这种类型的构造函数允许自动转换为正在构造的class。
正如@john 提到的,要禁用此行为,我们使用 explicit
说明符。
explicit B(A*)
和 foo()
不再被接受。
此外,如您所见,在我的 B
版本中,没有成员 A* ptr;
- 它不是必需的。
进一步了解 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);
会编译并调用构造函数。