接上文
能不能不用std::move()让移动构造函数调用成员和基类的移动构造函数?
可以,如果你没有自定义的操作,使用=default;即可,对拷贝构造函数也适用,赋值也是,计划用另外的文章来讲相关的知识;
C++的模板,又是一个偷懒利器,同时跟构造函数一样,也是幻觉制造机
正如我所说,简单和复杂并没有明确的界限,模板的便利有个前提,你对它了如指掌,构造函数也是一样;
有些数据类型,只是某些特定性质存在差异,处理逻辑是一样的,模板就是这个的干活,如:数值的 float 和 double,字符的 char 和 wchar 等;
那又怎么样,不就是多个模板参数吗?
其实也不怎么样,主要是在模板定义内,由于参数可以省略,编译器无法识别是模板,还是类型,还是构造函数,当然新的C++标准可能会解决这个问题;
就好像枚举,如果两个枚举的项的名称相同,就会出现重名错误,而C++11新增的强枚举类型则可以重名;
越扯越长,我们还是说说构造函数吧
那是我对小姐姐,呸呸,对C++最感兴趣的部分
直接把上文的类,全部模板化一遍,分别是:
BaseT.hpp
template<class T>
class BaseT {
protected:
// for further test
T *ptr;
public:
BaseT() { printf("BaseT::BaseT(), this=%p\n", this); }
BaseT(const BaseT &rhs) { printf("BaseT::BaseT(const BaseT &rhs), this=%p, &rhs=%p\n", this, &rhs); }
BaseT(BaseT &&rhs) { printf("BaseT::BaseT(BaseT &&rhs), this=%p, &rhs=%p\n", this, &rhs); }
BaseT(T *p) { printf("BaseT::BaseT(T *p), this=%p\n", this); this->ptr = p; }
virtual ~BaseT() { printf("BaseT::~BaseT(), this=%p\n", this); }
BaseT &operator=(const BaseT &rhs)
{
printf("BaseT::operator=(const BaseT &rhs), this=%p, &rhs=%p\n", this, &rhs);
if (&rhs != this) {}
return *this;
}
BaseT &operator=(BaseT &&rhs)
{
printf("BaseT::operator=(const BaseT &&rhs), this=%p, &rhs=%p\n", this, &rhs);
if (&rhs != this) {}
return *this;
}
};
MemberObjectT.hpp
template<class T>
class MemberObjectT {
public:
MemberObjectT() { printf("MemberObjectT::MemberObjectT(), this=%p\n", this); }
MemberObjectT(const MemberObjectT &rhs) { printf("MemberObjectT::MemberObjectT(const MemberObjectT &rhs), this=%p\n", this); }
MemberObjectT(MemberObjectT &&rhs) { printf("MemberObjectT::MemberObjectT(MemberObjectT &&rhs), this=%p\n", this); }
virtual ~MemberObjectT() { printf("MemberObjectT::~MemberObjectT(), this=%p\n", this); }
MemberObjectT &operator=(const MemberObjectT &rhs)
{
printf("MemberObjectT::operator=(const MemberObjectT &rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
MemberObjectT &operator=(MemberObjectT &&rhs)
{
printf("MemberObjectT::operator=(const MemberObjectT &&rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
};
ObjectT.hpp
template<class T>
class ObjectT : public BaseT<T> {
protected:
MemberObjectT<T> mo;
public:
ObjectT() { printf("ObjectT::ObjectT(), this=%p\n", this); }
ObjectT(const ObjectT &rhs) { printf("ObjectT::ObjectT(const ObjectT &rhs), this=%p\n", this); }
ObjectT(ObjectT &&rhs) { printf("ObjectT::ObjectT(ObjectT &&rhs), this=%p\n", this); }
ObjectT(T *p) { printf("ObjectT::ObjectT(T *p), this=%p\n", this); }
virtual ~ObjectT() { printf("ObjectT::~ObjectT(), this=%p\n", this); }
ObjectT &operator=(const ObjectT &rhs)
{
printf("ObjectT::operator=(const ObjectT &rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
ObjectT &operator=(ObjectT &&rhs)
{
printf("ObjectT::operator=(const ObjectT &&rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
ObjectT operator+(const ObjectT &rhs) const
{
printf("ObjectT::operator+(const ObjectT &rhs), this=%p\n", this);
ObjectT o1;
return o1;
}
};
现在执行:
test_cpp<BaseT<int>, ObjectT<int>>();
结果
BaseT::BaseT(), this=000000573E15F168
MemberObjectT::MemberObjectT(), this=000000573E15F178
ObjectT::ObjectT(), this=000000573E15F168
BaseT::BaseT(), this=000000573E15F198
MemberObjectT::MemberObjectT(), this=000000573E15F1A8
ObjectT::ObjectT(const ObjectT &rhs), this=000000573E15F198
BaseT::BaseT(), this=000000573E15F1C8
MemberObjectT::MemberObjectT(), this=000000573E15F1D8
ObjectT::ObjectT(const ObjectT &rhs), this=000000573E15F1C8
ObjectT::operator+(const ObjectT &rhs), this=000000573E15F168
BaseT::BaseT(), this=000000573E15EFF8
MemberObjectT::MemberObjectT(), this=000000573E15F008
ObjectT::ObjectT(), this=000000573E15EFF8
BaseT::BaseT(), this=000000573E15F1F8
MemberObjectT::MemberObjectT(), this=000000573E15F208
ObjectT::ObjectT(ObjectT &&rhs), this=000000573E15F1F8
ObjectT::~ObjectT(), this=000000573E15EFF8
MemberObjectT::~MemberObjectT(), this=000000573E15F008
BaseT::~BaseT(), this=000000573E15EFF8
BaseT::BaseT(), this=00000159706A27B0
MemberObjectT::MemberObjectT(), this=00000159706A27C0
ObjectT::ObjectT(T *p), this=00000159706A27B0
ObjectT::operator=(const ObjectT &rhs), this=000000573E15F198
ObjectT::operator+(const ObjectT &rhs), this=000000573E15F168
BaseT::BaseT(), this=000000573E15EFF8
MemberObjectT::MemberObjectT(), this=000000573E15F008
ObjectT::ObjectT(), this=000000573E15EFF8
BaseT::BaseT(), this=000000573E15F348
MemberObjectT::MemberObjectT(), this=000000573E15F358
ObjectT::ObjectT(ObjectT &&rhs), this=000000573E15F348
ObjectT::~ObjectT(), this=000000573E15EFF8
MemberObjectT::~MemberObjectT(), this=000000573E15F008
BaseT::~BaseT(), this=000000573E15EFF8
ObjectT::operator=(const ObjectT &&rhs), this=000000573E15F1C8
ObjectT::~ObjectT(), this=000000573E15F348
MemberObjectT::~MemberObjectT(), this=000000573E15F358
BaseT::~BaseT(), this=000000573E15F348
ObjectT::~ObjectT(), this=00000159706A27B0
MemberObjectT::~MemberObjectT(), this=00000159706A27C0
BaseT::~BaseT(), this=00000159706A27B0
ObjectT::~ObjectT(), this=000000573E15F1F8
MemberObjectT::~MemberObjectT(), this=000000573E15F208
BaseT::~BaseT(), this=000000573E15F1F8
ObjectT::~ObjectT(), this=000000573E15F1C8
MemberObjectT::~MemberObjectT(), this=000000573E15F1D8
BaseT::~BaseT(), this=000000573E15F1C8
ObjectT::~ObjectT(), this=000000573E15F198
MemberObjectT::~MemberObjectT(), this=000000573E15F1A8
BaseT::~BaseT(), this=000000573E15F198
ObjectT::~ObjectT(), this=000000573E15F168
MemberObjectT::~MemberObjectT(), this=000000573E15F178
BaseT::~BaseT(), this=000000573E15F168
看来没什么可以说的,跟上文的情形一样,只是模板类具体化了而已;
模板类如何显式调用基类的构造函数?
我们把Object2模板化为ObjectT2.hpp
template<class T>
class ObjectT2 : public BaseT<T> {
protected:
MemberObjectT<T> mo;
public:
ObjectT2() { printf("ObjectT2::ObjectT2(), this=%p\n", this); }
ObjectT2(const ObjectT2 &rhs) : BaseT<T>(rhs), mo(rhs.mo) { printf("ObjectT2::ObjectT2(const ObjectT2 &rhs), this=%p\n", this); }
ObjectT2(ObjectT2 &&rhs) : BaseT<T>(rhs), mo(rhs.mo) { printf("ObjectT2::ObjectT2(ObjectT2 &&rhs), this=%p\n", this); }
ObjectT2(T *p) : BaseT<T>(p) { printf("ObjectT2::ObjectT2(T *p), this=%p\n", this); }
virtual ~ObjectT2() { printf("ObjectT2::~ObjectT2(), this=%p\n", this); }
ObjectT2 &operator=(const ObjectT2 &rhs)
{
printf("ObjectT2::operator=(const ObjectT2 &rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
ObjectT2 &operator=(ObjectT2 &&rhs)
{
printf("ObjectT2::operator=(const ObjectT2 &&rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
ObjectT2 operator+(const ObjectT2 &rhs) const
{
printf("ObjectT2::operator+(const ObjectT2 &rhs), this=%p\n", this);
ObjectT2 o1;
return o1;
}
};
菩萨保佑,编译通过,现在就看看this指针是不是所期待的那样
执行
test_cpp<BaseT<int>, ObjectT2<int>>();
结果
BaseT::BaseT(), this=000000573E15F168
MemberObjectT::MemberObjectT(), this=000000573E15F178
ObjectT2::ObjectT2(), this=000000573E15F168
BaseT::BaseT(const BaseT &rhs), this=000000573E15F198, &rhs=000000573E15F168
MemberObjectT::MemberObjectT(const MemberObjectT &rhs), this=000000573E15F1A8
ObjectT2::ObjectT2(const ObjectT2 &rhs), this=000000573E15F198
BaseT::BaseT(const BaseT &rhs), this=000000573E15F1C8, &rhs=000000573E15F168
MemberObjectT::MemberObjectT(const MemberObjectT &rhs), this=000000573E15F1D8
ObjectT2::ObjectT2(const ObjectT2 &rhs), this=000000573E15F1C8
ObjectT2::operator+(const ObjectT2 &rhs), this=000000573E15F168
BaseT::BaseT(), this=000000573E15EFF8
MemberObjectT::MemberObjectT(), this=000000573E15F008
ObjectT2::ObjectT2(), this=000000573E15EFF8
BaseT::BaseT(const BaseT &rhs), this=000000573E15F1F8, &rhs=000000573E15EFF8
MemberObjectT::MemberObjectT(const MemberObjectT &rhs), this=000000573E15F208
ObjectT2::ObjectT2(ObjectT2 &&rhs), this=000000573E15F1F8
ObjectT2::~ObjectT2(), this=000000573E15EFF8
MemberObjectT::~MemberObjectT(), this=000000573E15F008
BaseT::~BaseT(), this=000000573E15EFF8
BaseT::BaseT(T *p), this=00000159706A2210
MemberObjectT::MemberObjectT(), this=00000159706A2220
ObjectT2::ObjectT2(T *p), this=00000159706A2210
ObjectT2::operator=(const ObjectT2 &rhs), this=000000573E15F198
ObjectT2::operator+(const ObjectT2 &rhs), this=000000573E15F168
BaseT::BaseT(), this=000000573E15EFF8
MemberObjectT::MemberObjectT(), this=000000573E15F008
ObjectT2::ObjectT2(), this=000000573E15EFF8
BaseT::BaseT(const BaseT &rhs), this=000000573E15F348, &rhs=000000573E15EFF8
MemberObjectT::MemberObjectT(const MemberObjectT &rhs), this=000000573E15F358
ObjectT2::ObjectT2(ObjectT2 &&rhs), this=000000573E15F348
ObjectT2::~ObjectT2(), this=000000573E15EFF8
MemberObjectT::~MemberObjectT(), this=000000573E15F008
BaseT::~BaseT(), this=000000573E15EFF8
ObjectT2::operator=(const ObjectT2 &&rhs), this=000000573E15F1C8
ObjectT2::~ObjectT2(), this=000000573E15F348
MemberObjectT::~MemberObjectT(), this=000000573E15F358
BaseT::~BaseT(), this=000000573E15F348
ObjectT2::~ObjectT2(), this=00000159706A2210
MemberObjectT::~MemberObjectT(), this=00000159706A2220
BaseT::~BaseT(), this=00000159706A2210
ObjectT2::~ObjectT2(), this=000000573E15F1F8
MemberObjectT::~MemberObjectT(), this=000000573E15F208
BaseT::~BaseT(), this=000000573E15F1F8
ObjectT2::~ObjectT2(), this=000000573E15F1C8
MemberObjectT::~MemberObjectT(), this=000000573E15F1D8
BaseT::~BaseT(), this=000000573E15F1C8
ObjectT2::~ObjectT2(), this=000000573E15F198
MemberObjectT::~MemberObjectT(), this=000000573E15F1A8
BaseT::~BaseT(), this=000000573E15F198
ObjectT2::~ObjectT2(), this=000000573E15F168
MemberObjectT::~MemberObjectT(), this=000000573E15F178
BaseT::~BaseT(), this=000000573E15F168
逐个检查,直到移动赋值 o3=o1+o2
善哉,所有指针正常:
1.基类和成员,未指定时调用的是默认构造函数(我们通过上文已经知晓)
2.移动构造函数的右值,在函数内是左值(我们通过上文已经知晓)
3.可以使用 template_name<...> 在初始化列表中指定基类的构造函数
那么
让我们用小姐姐,呸呸,用C++再做点更加离(变)奇(态)的事情
用名称空间隔离,然后派生同名类模板:
namespace Demo
{
template<class T>
class BaseT {
protected:
// for further test
T *ptr;
public:
BaseT() { printf("BaseT::BaseT(), this=%p\n", this); }
BaseT(const BaseT &rhs) { printf("BaseT::BaseT(const BaseT &rhs), this=%p, &rhs=%p\n", this, &rhs); }
BaseT(BaseT &&rhs) { printf("BaseT::BaseT(BaseT &&rhs), this=%p, &rhs=%p\n", this, &rhs); }
BaseT(T *p) { printf("BaseT::BaseT(T *p), this=%p\n", this); this->ptr = p; }
virtual ~BaseT() { printf("BaseT::~BaseT(), this=%p\n", this); }
BaseT &operator=(const BaseT &rhs)
{
printf("BaseT::operator=(const BaseT &rhs), this=%p, &rhs=%p\n", this, &rhs);
if (&rhs != this) {}
return *this;
}
BaseT &operator=(BaseT &&rhs)
{
printf("BaseT::operator=(const BaseT &&rhs), this=%p, &rhs=%p\n", this, &rhs);
if (&rhs != this) {}
return *this;
}
};
template<class T>
class MemberObjectT {
public:
MemberObjectT() { printf("MemberObjectT::MemberObjectT(), this=%p\n", this); }
MemberObjectT(const MemberObjectT &rhs) { printf("MemberObjectT::MemberObjectT(const MemberObjectT &rhs), this=%p\n", this); }
MemberObjectT(MemberObjectT &&rhs) { printf("MemberObjectT::MemberObjectT(MemberObjectT &&rhs), this=%p\n", this); }
virtual ~MemberObjectT() { printf("MemberObjectT::~MemberObjectT(), this=%p\n", this); }
MemberObjectT &operator=(const MemberObjectT &rhs)
{
printf("MemberObjectT::operator=(const MemberObjectT &rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
MemberObjectT &operator=(MemberObjectT &&rhs)
{
printf("MemberObjectT::operator=(const MemberObjectT &&rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
};
}
template<class T>
class BaseT : public Demo::BaseT<T> {
protected:
Demo::MemberObjectT<T> mo;
public:
BaseT() { printf("::BaseT::BaseT(), this=%p\n", this); }
BaseT(const BaseT &rhs) : Demo::BaseT<T>(rhs), mo(rhs.mo) { printf("::BaseT::BaseT(const BaseT &rhs), this=%p\n", this); }
BaseT(BaseT &&rhs) : Demo::BaseT<T>(rhs), mo(rhs.mo) { printf("::BaseT::BaseT(BaseT &&rhs), this=%p\n", this); }
BaseT(T *p) : Demo::BaseT<T>(p) { printf("::BaseT::BaseT(char *p), this=%p\n", this); }
virtual ~BaseT() { printf("::BaseT::~BaseT(), this=%p\n", this); }
BaseT &operator=(const BaseT &rhs)
{
printf("::BaseT::operator=(const BaseT &rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
BaseT &operator=(BaseT &&rhs)
{
printf("::BaseT::operator=(const BaseT &&rhs), this=%p\n", this);
if (&rhs != this) {}
return *this;
}
BaseT operator+(const BaseT &rhs) const
{
printf("::BaseT::operator+(const BaseT &rhs), this=%p\n", this);
BaseT o1;
return o1;
}
};
执行
test_cpp<Demo::BaseT<int>, BaseT<int>>();
我知道,那么都清楚做法
那么只是不想动手去试,而到处寻找已有的答案而已
这就是我们国家很少有技术创新的根源,中国人多数喜欢吃现成饭,所以测试结果(略)
硬件:Intel? Core? i5-1035G1
系统:Windows 10 Professional
软件:Microsoft Visual Studio 2015 Enterprise
|