IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++简单问题搞复杂之构造函数与初始化(模板类) -> 正文阅读

[C++知识库]C++简单问题搞复杂之构造函数与初始化(模板类)

上文

能不能不用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

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:02:42  更:2022-07-17 16:06:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 5:10:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码