【深入理解C++】隐式构造与explicit

2023-11-06

1.隐式构造

C++ 中存在隐式构造的现象,即在某些情况下,会隐式调用单参数的构造函数。

1.1 情况一

#include <iostream>

using namespace std;

class Student
{
private:
	int age;

public:
	Student()
	{
		age = 0;
		cout << "Student() - " << this << endl;
	}
	Student(int v)
	{
		age = v;
		cout << "Student(int v) - " << this << endl;
	}
	Student(const Student& stu) // 拷贝构造函数
	{
		age = stu.age;
		cout << "Student(const Student& stu) - " << this << endl;
	}
	Student& operator=(const Student& stu) // 拷贝赋值运算符
	{
		age = stu.age;
		cout << "Student& operator=(const Student& stu) - " << this << endl;
		return *this;
	}
	~Student()
	{
		cout << "~Student() - " << this << endl;
	}
	void display()
	{
		cout << "display() - " << this << endl;
	}
};

int main()
{
	Student stu1 = 20;

	return 0;
}

在这里插入图片描述

1.2 情况二

#include <iostream>

using namespace std;

class Student
{
private:
	int age;

public:
	Student()
	{
		age = 0;
		cout << "Student() - " << this << endl;
	}
	Student(int v)
	{
		age = v;
		cout << "Student(int v) - " << this << endl;
	}
	Student(const Student& stu) // 拷贝构造函数
	{
		age = stu.age;
		cout << "Student(const Student& stu) - " << this << endl;
	}
	Student& operator=(const Student& stu) // 拷贝赋值运算符
	{
		age = stu.age;
		cout << "Student& operator=(const Student& stu) - " << this << endl;
		return *this;
	}
	~Student()
	{
		cout << "~Student() - " << this << endl;
	}
	void display()
	{
		cout << "display() - " << this << endl;
	}
};

void test1(Student stu)
{

}

int main()
{
	test1(30);

	return 0;
}

在这里插入图片描述

1.3 情况三

#include <iostream>

using namespace std;

class Student
{
private:
	int age;

public:
	Student()
	{
		age = 0;
		cout << "Student() - " << this << endl;
	}
	Student(int v)
	{
		age = v;
		cout << "Student(int v) - " << this << endl;
	}
	Student(const Student& stu) // 拷贝构造函数
	{
		age = stu.age;
		cout << "Student(const Student& stu) - " << this << endl;
	}
	Student& operator=(const Student& stu) // 拷贝赋值运算符
	{
		age = stu.age;
		cout << "Student& operator=(const Student& stu) - " << this << endl;
		return *this;
	}
	~Student()
	{
		cout << "~Student() - " << this << endl;
	}
	void display()
	{
		cout << "display() - " << this << endl;
	}
};

Student test2()
{
	return 40;
}

int main()
{
	test2();

	return 0;
}

在这里插入图片描述

2.explicit

上面的三个代码都隐式调用了单参数的构造函数,将一个整数类型 int 转换为类类型 Student。但是,这种隐式类型转换有些不伦不类,容易让人产生疑惑,有什么办法可以阻止这种用法呢?

答案:使用 explicit 关键字。explicit 指定构造函数或转换函数为显式,即不能用于隐式转换和复制初始化。

#include <iostream>

using namespace std;

class Student
{
private:
	int age;

public:
	Student()
	{
		age = 0;
		cout << "Student() - " << this << endl;
	}
	explicit Student(int a)
	{
		age = a;
		cout << "Student(int v) - " << this << endl;
	}
	Student(const Student& stu) // 拷贝构造函数
	{
		age = stu.age;
		cout << "Student(const Student& stu) - " << this << endl;
	}
	Student& operator=(const Student& stu) // 拷贝赋值运算符
	{
		age = stu.age;
		cout << "Student& operator=(const Student& stu) - " << this << endl;
		return *this;
	}
	~Student()
	{
		cout << "~Student() - " << this << endl;
	}
	void display()
	{
		cout << "display() - " << this << endl;
	}
};

int main()
{
	Student stu1 = 18; // 报错
	Student stu2 = { 20 }; // 报错

	return 0;
}

在这里插入图片描述

explicit 关键字只对带一个参数的类构造函数有效,如果类构造函数参数大于或等于两个,是不会产生隐式转换的,所以 explicit 关键字也就无效了。

但是,如果类构造函数除了第一个参数以外的其他参数都有默认值,此时等效于只有一个参数的类构造函数,那么 explicit 关键字依然有效。

#include <iostream>

using namespace std;

class Student
{
private:
	int age;
	int height;

public:
	Student()
	{
		age = 0;
		height = 0;
		cout << "Student() - " << this << endl;
	}
	explicit Student(int a, int b = 180)
	{
		age = a;
		height = b;
		cout << "Student(int v) - " << this << endl;
	}
	Student(const Student& stu) // 拷贝构造函数
	{
		age = stu.age;
		height = stu.height;
		cout << "Student(const Student& stu) - " << this << endl;
	}
	Student& operator=(const Student& stu) // 拷贝赋值运算符
	{
		age = stu.age;
		height = stu.height;
		cout << "Student& operator=(const Student& stu) - " << this << endl;
		return *this;
	}
	~Student()
	{
		cout << "~Student() - " << this << endl;
	}
	void display()
	{
		cout << "display() - " << this << endl;
	}
};

int main()
{
	Student stu1 = 18; // 报错
	Student stu2 = { 20 }; // 报错

	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【深入理解C++】隐式构造与explicit 的相关文章

  • C++ 维护子类对象的混合集合

    如果我在这里错过了一个相当基本的概念 我很抱歉 但我正在尝试弄清楚如何维护多个类类型的集合 所有类类型都派生自同一个父类 并且在检索它们时仍然可以访问它们的特定于子类的方法从集合中 作为上下文 我有一个基类 BaseClass 和许多类 例
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 为什么在 WebApi 上下文中在 using 块中使用 HttpClient 是错误的?

    那么 问题是为什么在 using 块中使用 HttpClient 是错误的 但在 WebApi 上下文中呢 我一直在读这篇文章不要阻止异步代码 https blog stephencleary com 2012 07 dont block
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • 将 Long 转换为 DateTime 从 C# 日期到 Java 日期

    我一直尝试用Java读取二进制文件 而二进制文件是用C 编写的 其中一些数据包含日期时间数据 当 DateTime 数据写入文件 以二进制形式 时 它使用DateTime ToBinary on C 为了读取 DateTime 数据 它将首
  • C# 存档中的文件列表

    我正在创建一个 FileFinder 类 您可以在其中进行如下搜索 var fileFinder new FileFinder new string C MyFolder1 C MyFolder2 new string
  • 启动时的 Excel 加载项

    我正在使用 Visual C 创建 Microsoft Excel 的加载项 当我第一次创建解决方案时 它包含一个名为 ThisAddIn Startup 的函数 我在这个函数中添加了以下代码 private void ThisAddIn
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • 打印大型 WPF 用户控件

    我有一个巨大的数据 我想使用 WPF 打印 我发现WPF提供了一个PrintDialog PrintVisual用于打印派生的任何 WPF 控件的方法Visual class PrintVisual只会打印一页 因此我需要缩放控件以适合页面
  • String.Empty 与 "" [重复]

    这个问题在这里已经有答案了 可能的重复 String Empty 和 有什么区别 https stackoverflow com questions 151472 what is the difference between string
  • OpenGL:仅获取模板缓冲区而没有深度缓冲区?

    我想获取一个模板缓冲区 但如果可能的话 不要承受附加深度缓冲区的开销 因为我不会使用它 我发现的大多数资源表明 虽然模板缓冲区是可选的 例如 排除它以利于获得更高的深度缓冲区精度 但我还没有看到任何请求并成功获取仅 8 位模板缓冲区的代码
  • 使用 C 在 OS X 中获取其他进程的 argv

    我想获得其他进程的argv 例如ps 我使用的是在 Intel 或 PowerPC 上运行的 Mac OS X 10 4 11 首先 我阅读了 ps 和 man kvm 的代码 然后编写了一些 C 代码 include
  • GCC 的“-Wl,option”和“-Xlinker option”语法之间有区别吗?

    我一直在查看一些配置文件 并且看到它们都被使用 尽管在不同的体系结构上 如果您在 Linux 机器上使用 GCC 将选项传递给链接器的两种语法之间有区别吗 据我所知 阅读 GCC 手册时 他们的解释几乎相同 From man gcc Xli
  • 如何将十六进制字符串转换为无符号长整型?

    我有以下十六进制值 CString str str T FFF000 如何将其转换为unsigned long 您可以使用strtol作用于常规 C 字符串的函数 它使用指定的基数将字符串转换为 long long l strtol str
  • 不区分大小写的字符串比较 C++ [重复]

    这个问题在这里已经有答案了 我知道有一些方法可以进行忽略大小写的比较 其中涉及遍历字符串或一个good one https stackoverflow com questions 11635 case insensitive string

随机推荐