我只是在玩弄了解智能指针并试图制作我的但我遇到的情况我并不完全理解。这是代码:
#include <iostream>
template <class T>
class Holder
{
private:
T * obj;
public:
Holder(T * tt) : obj(tt)
{
std::cout << "ctor : " << tt->dummy << std::endl;
}
T * operator -> ()
{
return obj;
}
operator bool()
{
return obj;
}
T * const get() const
{
return obj;
}
void reset() {swap(0);}
void swap(T * other)
{
obj = other;
}
Holder & operator = (const Holder& holder)
{
obj = holder.get();
return *this;
}
Holder(const Holder & holder) : obj(holder.get()) {}
};
class A
{
public:
int dummy;
A(int a) : dummy(a) {}
};
int main ()
{
A * a = new A(1);
Holder<A> holder(a);
A * b = new A(2);
holder = b;
std::cout << holder->dummy << std::endl;
return 0;
}
代码编译并在holder = b;
行上调用Holder
类的构造函数。我以为编译器会给出错误。它不是assingment运算符,但为什么调用构造函数?
答案 0 :(得分:14)
holder = b
尝试从b
分配到Holder
。 b
的类型为A*
,holder
的类型为Holder<A>
。
Holder
模板定义了来自同一Holder
类型的另一个实例的分配,因此编译器会查找从A*
到{{1}的转换 }。它找到了构造函数,并使用它。
可能只使用一个参数的构造函数可用于隐式转换,除非使用Holder<A>
关键字标记它们。
答案 1 :(得分:4)
调用构造函数和赋值运算符。您可以通过在operator =
打印内容来检查这一点。
这是因为operator =
定义为const Holder &
,b
类型为A *
。因此,首先调用Holder(T *)
构造函数来创建临时对象,然后通过holder
将此对象分配给operator =
。
如果定义operator =(const T *)
,则只会调用赋值运算符。
答案 2 :(得分:1)
我没有看到采用A *
右侧的赋值运算符的版本 A* a = new A(1);
Holder<A> holder(a);
A* b = new A(2);
// assigning object of type A* to Holder<A>
holder = b;
// No appropriate assignment operator provide.
// But a constructor is available to convert RHS parameter to correct type.
// So compiler generates the following code:
holder = Holder<A>(b);
// There is an appropriate assignment operator for this.
// So it compiles.
答案 3 :(得分:0)
你有一个构造函数采用T *。 你的赋值有一个rhs指针,所以它用该指针作为参数构造一个temp-obj,并将它赋给holder。