C++类隐式转换场景下scopedptr对象的所属类型及调用权限问题
#include <iostream> using namespace std; class temp { public: temp() { std::cout << "Constructor created." << std::endl; } ~temp() { std::cout << "Deconstructor called." << std::endl; } }; class scopedptr { private: temp* ptr; public: scopedptr(temp* p) { ptr = p; std::cout << "scoped" << std::endl; } ~scopedptr() { delete ptr; } }; int main() { { scopedptr a = new temp(); } }
问题1:对象a的类型归属
scopedptr a = new temp();中定义的a明确是scopedptr类的对象,和temp类没有直接的类型从属关系。
问题2:a可以调用的成员范围
a只能调用scopedptr类中定义的public成员,完全不能直接调用temp类的成员。如果要通过a访问内部持有的temp对象的成员,需要在scopedptr中额外重载*解引用运算符或者->成员访问运算符才可以,示例如下:
// 在scopedptr类中添加如下代码 temp* operator->() { return ptr; } temp& operator*() { return *ptr; }
添加后就可以通过a->xxx或者(*a).xxx访问temp的公开成员了。
问题3:触发的隐式转换逻辑
这个语句能正常执行的核心原因是scopedptr的构造函数scopedptr(temp* p)没有加explicit修饰,属于允许隐式转换的构造函数,执行逻辑分三步:
- 先执行
new temp(),在堆上创建一个temp类的对象,返回该对象的temp*类型指针 - 编译器发现赋值右侧是
temp*类型,左侧需要scopedptr类型,自动触发隐式转换:用得到的temp*指针作为参数,调用scopedptr的单参数构造函数,生成一个临时的scopedptr对象 - 用这个临时的scopedptr对象拷贝构造得到对象a(C++17及以后版本会做复制消除,直接在a的内存空间构造对象,不会产生临时对象)
如果不想允许这种隐式转换,只需要给scopedptr的构造函数加上explicit修饰:explicit scopedptr(temp* p),这时原来的语句就会编译报错,必须写成scopedptr a(new temp());才可以正常编译。
内容的提问来源于stack exchange,提问作者aman
相关产品推荐
相关产品推荐

