C++显式构造函数 [翻译]

C++中的显式构造和隐式构造 本文主要介绍了显式构造和隐式构造的使用场景。 阅读详情

原文地址:http://www.codeproject.com/KB/cpp/explicit_constructor_CPP.aspx
简介

构造函数的确能使你的类变的简单优雅,它也是一个基本的函数,可以由编译器以默认的方式提供给你,即默认构造函数。在c++中,如果你只写一行代码。
Class A{};
编译器会提供给你一个默认的、无参数的构造函数,并伴随一个析构函数,一个拷贝构造函数(copy Constructor),一个拷贝复制操作符(copy assignment operator)

背景

那么什么是显式构造函数?
为了方便理解显式构造函数,我们首先需要理解隐式转换,让我们看一下它在代码中的作用,以及什么时候不需要这些特性。
使用以下代码,例1:思考下面这个传统而简单的复数类:

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;
  4. class complexNumbers {
  5.   double real, img;
  6. public:
  7.   complexNumbers() : real(0), img(0) { }
  8.   complexNumbers(const complexNumbers& c) { real = c.real; img = c.img; }
  9.   complexNumbers( double r, double i = 0.0) { real = r; img = i; }
  10.   friend void display(complexNumbers cx);
  11. };
  12. void display(complexNumbers cx){
  13.   cout<<"Real Part: "<<cx.real<<" Imag Part: "<<cx.img<<endl;
  14. }
  15. int main() {
  16.   complexNumbers one(1);
  17.   complexNumbers five = 5;
  18.   display(one);
  19.   display(five);
  20.   return 0;
  21. }

 

这个复数类很简单,它包括实数复数两部分,代码定义了一个默认的构造函数,一个拷贝构造函数,以及着重定义了另一个构造函数,用它来帮我们做一些隐式的构造。
在main函数中,我们首先创建了一个名为one 和一个名为 five的对象,由于隐式转换的作用,它们都能成功调用。故对象one的实数为1,虚数为 0;对象five的实数为5,虚数0.我们可以使用复数类中的 “display”方法打印出来,对隐式转换的理解,这是一个很好的例子。输出结果如下:

Real Part: 1 Imag Part: 0
Real Part: 5 Imag Part: 0

 

下面我们考虑这个例子:

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;
  4. class complexNumbers {
  5.   double real, img;
  6. public:
  7.   complexNumbers() : real(0), img(0) { }
  8.   complexNumbers(const complexNumbers& c) { real = c.real; img = c.img; }
  9.   complexNumbers( double r, double i = 0.0) { real = r; img = i; }
  10.   friend void display(complexNumbers cx);
  11. };
  12. void display(complexNumbers cx){
  13.   cout<<"Real Part: "<<cx.real<<" Imag Part: "<<cx.img<<endl;
  14. }
  15. int main() {
  16.   complexNumbers one(1);
  17.   display(one);
  18.   display(300);
  19.   return 0;
  20. }

 

类似的例子,只是在main方法中多加了一行,display(300),继续,输出结果变为:

Real Part: 1 Imag Part: 0
Real Part: 300 Imag Part: 0
 

“邦”!!!这不是我们希望的结果,首先代码本身就不清楚,display(300)什么意思?display 方法的参数期待的是复数类的一个对象/实例,而300根本不是,那么这种情况是如何发生的呢?
因为display方法期待一个复数类的一个对象/实例,当我们把300这个十进制数传进去是,在将300这个十进制数传到复数类的一个临时对象时,发生了一次隐式转换。(因此,300就赋值给临时对象的实数了)。
那么怎么解决这种情况呢??
很简单,强制编译器只能通过显示构造来创建对象,技巧如下:

  1. #include <iostream>
  2. using std::cout;
  3. using std::endl;
  4. class complexNumbers {
  5.   double real, img;
  6. public:
  7.   complexNumbers() : real(0), img(0) { }
  8.   complexNumbers(const complexNumbers& c) { real = c.real; img = c.img; }
  9.   explicit complexNumbers( double r, double i = 0.0) { real = r; img = i; }
  10.   friend void display(complexNumbers cx);
  11. };
  12. void display(complexNumbers cx){
  13.   cout<<"Real Part: "<<cx.real<<" Imag Part: "<<cx.img<<endl;
  14. }
  15. int main() {
  16.   complexNumbers one(1);
  17.   display(one);
  18.   complexNumbers two =2;
  19.   display(200);
  20.   return 0;
  21. }

 

思考下面的语句:

  1. explicit complexNumbers( double r, double i = 0.0) { real = r; img = i; }

此时我们强制编译器在这段代码中不能使用隐式转换,如果程序员写包含隐式转换的代码,编译器将返回一个错误。

  1. bash-3.2$ g++ -g -o hello test2.cpp 
  2. test2.cpp: In function ‘int main()’:
  3. test2.cpp:22: error: conversion from ‘int’ to non-scalar type ‘complexNumbers’ requested
  4. test2.cpp:23: error: conversion from ‘int’ to non-scalar type ‘complexNumbers’ requested

 

鉴于此,程序员应当用下面的方法实现:
display(complexNumbers(200)); //只允许显示转换…………

 

 

C++模板实例化:隐式、显式与extern声明详解 C++模板是泛型编程的核心机制,它允许编写与类型无关的通用代码。其工作原理是编译器根据具体类型参数生成特化版本,这一过程称为模板实例化。从技术价值看,模板实现了代码复用与类型安全,是STL等标准库的基石。在工程实践中,实例化策略直接影响编译速度、代码体积与二进制组织。隐式实例化由编译器自动完成,要求模板定义对每个编译单元可见,常导致重复编译;显式实例化定义则让开发者精确控制代码生成位置,适用于库开发与编译优化;而C++11引入的显式实例化声明(extern template)能有效抑制重复实例化,显著提升大 阅读详情

相关推荐

【C++】B2115 密码翻译

在计算机编程中,解题不仅仅是通过完成任务,还能帮助我们培养思维的灵活性和严谨性。通过对这道题《密码翻译》(题号:B2115)进行详细的分析和思考,我们不仅能更好地理解 C++ 的基础应用,还能够在实际操作中进行思维优化,提升代码效率与可读性。在本篇文章中,我将详细讲解老师的做法、我的做法以及两者之间的优缺点,最后我会提出如何修正代码中的问题,并对本题做一些拓展与延伸,帮助大家更深入地理解这类问题。 2025.2.3-✍25min

禅宗里有一个词叫做“因缘和合”。 所谓因缘,是指事件要发生所必须的条件。因缘和合就是当你聚集了这件事的一切条件,它就会自然而然的发生。“它就会自然而然的发生”,这种朴素而坚定的价值观让我们感到无比安心,安心到可以不用有任何担心焦虑。 3388

【C++】构造函数(包括默认构造函数) ,析构函数的使用与特性

则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

m0_74774759的博客 1869

54、C++模板显式实例化与显式特化全解析

本文深入解析了C++中模板的显式实例化与显式特化,详细介绍了模板实例化的规则、语法要求以及应用场景。通过对比显式实例化和显式特化的功能、使用方式和编译行为,帮助开发者更好地理解它们的区别与适用场景。文章还结合实际案例,展示了如何在大型项目中使用显式实例化提升编译效率,以及如何通过显式特化为特定类型提供优化实现。掌握这些知识有助于编写更高效、可维护的C++模板代码。

rr23456的博客 85

c++的构造函数种类大全

从语法上讲,构造函数是与类同名的函数。功能是用于初始化数据成员。构造函数没有返回类型,参数可以有,也可以没有,没有参数的构造函数称为,也称为无参构造函数。有些情况下,必须提供默认的构造函数,否则就会编译报错。

weixin_48617416的博客 2094

《探秘 BME680温度湿度气压气体传感器模块:环境感知的卓越之选》:此文为AI自动生成

BME680 是一款由博世公司推出的集成环境传感器模块,在环境监测和物联网等领域中发挥着重要作用。它能够同时测量温度、湿度、气压和气体浓度等多个环境参数,为各种应用提供准确可靠的环境数据。该模块采用小巧的封装形式,便于集成到各种设备中,无论是智能家居、可穿戴设备还是工业监测系统,都能轻松适配。例如,在智能家居系统中,BME680 模块可以监测室内环境参数,如温度、湿度、气压和空气质量等。通过与智能家居控制器或智能手机应用程序的连接,用户可以实时了解室内环境状况,并根据需要进行调整。

zheng_ruiguo的专栏 1868

C语言新手必练:10个实战小项目带你快速上手(附完整代码)

本文为C语言初学者精选10个实战项目,从基础的温度转换器到高级的迷宫求解算法,涵盖输入输出、条件判断、循环控制、数组操作等核心知识点。每个项目配有完整代码和详细解析,帮助新手通过实践掌握编程思维,特别适合刚学完语法但缺乏实战经验的学习者。

weixin_29208077的博客 744

C/C++编程:显式构造函数(explicit )

如果类具有带一个参数的构造函数,或是如果除了一个参数之外的所有参数都具有默认值,则参数类型可以隐式转换为类类型(这样的构造函数也叫做隐式构造函数)。 例如,如果 Box 类具有一个类似于下面这样的构造函数: Box(int size): m_width(size), m_length(size), m_height(size){} 可以初始化 Box,如下所示: Box b = 42; 或将一个 int 传递给采用 Box 的函数: class ShippingOrder { public: S

OceanStar的博客 5332

防雷防浪涌电路设计

通信线路或者电源线路通常会铺设到户外,一旦线路铺到户外后,就需要考虑防雷的问题了,那么怎么设计保护电路,能够防止雷电等浪涌对电路的破坏呢?

manhuami2007的博客 1万+

(C++)类的构造函数——显示、隐式的调用构造函数及默认构造函数的显示、隐式方式

对于类,我们知道数据部分的访问状态是私有的,这将意味着程序不能直接访问数据成员,程序只能通过成员函数来访问数据成员。所以我们要设计合适的成员函数才能成功地将对象初始化,如果使数据成员成为公有,而不是私有,这使数据成为公有的违背了类将数据隐藏的一个特性。 其中,类构造函数专门用于构造新对象、将值赋给它们的数据成员。 构造函数的原型和函数头有一个有趣的特性——虽然没有返回值,但没有被声明为void型,实际上,构造函数没有声明类型。 构造函数的方法:(举个例子) 原函数: void Stock::acqui

小黄TIMTIM仔的博客 3899

【企业微信自建应用-前端篇】企业微信自建应用开发流程详细介绍

最近接到需求,需要我在企业微信端自建一个应用,用来接受PC端派发的工单,告警,公告等内容。这里写一个帖子汇总一下我经历的全流程开发,当然这是基础的流程啊。因为功能要求也不高。后面如果开发更多的东西再补充。

weixin_44265726的博客 9403

【机械臂算法】机械臂动力学参数辨识仿真

本文以puma560m机械臂为例子进行动力学参数辨识的讲解,puma560m可以在robotic toolbox中找到,这里以它真实机械臂对他的动力学参数进行辨识。此外这里还有要说的是,机械臂参数辨识其实是一个系统工程,其中和系统的机械、电子、嵌入式都有着很深的联系,并不是仿真这么简单的。

vrijheid的博客 7834

C++链接错误LNK2019:父类构造函数未定义导致的继承问题解析

在C++编程中,链接器(Linker)负责将编译后的目标文件合并为可执行程序,解决符号引用是其核心任务。当代码中引用了某个函数或变量,但链接器在所有输入文件中找不到其定义时,就会抛出LNK2019“无法解析的外部符号”错误。这一机制确保了程序的完整性,是构建可靠软件的基础。在面向对象编程中,构造函数负责对象的初始化,其正确实现直接影响程序的链接与运行。特别是在继承体系中,派生类构造函数会隐式调用基类的默认构造函数。如果基类依赖编译器隐式生成默认构造函数,且该构造函数未在任何翻译单元中被实际需要(如创建对象)

weixin_30263277的博客 403

20 硬件工程师笔面试高频考点真题解析——寄存器

摘要: 寄存器是由多个边沿触发的D触发器组成的多位存储单元,用于同步时序电路中的数据暂存、隔离毛刺、跨时钟域同步等。选型需考虑位宽、触发方式(边沿/电平)、异步控制、电气参数等。核心时序参数包括建立时间(Tsu)、保持时间(Thold)和时钟输出延迟(Tco)。寄存器广泛应用于时序逻辑、流水线分割、毛刺消除、跨时钟域同步及计数分频等场景。同步复位依赖时钟边沿,时序易收敛但需时钟支持;异步复位独立于时钟,上电可靠但需注意亚稳态风险。

XU157303764的博客 1342

仅仅说一下C++的显式实例化

关于显式实例化的资料,网上很多,看了看大多都是你抄我,我抄你,或者照搬cpp primer plus的说法,看得还是稀里糊涂。 理解这个需要先了解一下C++程序的编译。 先说一下编译。我们的程序代码不能直接被计算机的CPU识别并运行,因此,必须把类似英文自然语言的程序代码经过编译器的处理,变成计算机能识别的机器代码。 而计算机的机器代码是很朴素的,没有那么多的华丽胡哨的东西,只有一些简单的比如寻找地址、取出数据,数据加减乘除运算等基本内容,什么类啊、函数啊这些东西最终都会转化为这些朴素的代码。 原则上,我们

大柠檬的博客 1061

YOLOv11缝合改进Conv | SAConv在YOLOv11中的应用可切换空洞卷积与性能提升(附代码)

在本篇文章中,我们将深入探讨如何通过引入**SAConv**(Switchable Atrous Convolution,可切换空洞卷积)来优化YOLOv11网络结构,特别是在卷积操作方面的创新。我们会解析SAConv的核心原理和架构设计。

一键难忘的博客 953

YOLOv8 | 代码逐行解析(一) | 项目目录构造分析

Hello,大家好这次给大家带来的不是改进,是整个YOLOv8项目的分析,整个系列大概会更新7-10篇左右的文章,从项目的目录到每一个功能代码的都会进行详细的讲解,同时YOLOv8改进系列也突破了三十篇文章,最后预计本专栏持续更新会在年底更新上百篇的改进教程, 所以大家如果没有订阅专栏可以提前订阅以下。下面开始进行YOLOv8逐行解析的一篇——项目目录构造分析在这里给大家推荐我的YOLOv8改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,。

Snu77的博客 4万+

c++ 动态库 显式加载 隐式加载

window API 动态库隐式加载方式。 //库函数定义 int add(int a,int b) { return a+b; } 用户需要拿到库文档,文档记录了dll内的每个函数名和参数,利用函数指针指向库函数进行使用。 优点:dll库文件可以放入指定文件夹;无需引用头文件。 缺点:需要定义函数指针和加载dll函数文件;无法定义结构体进行传参。 隐式加载优缺点则反之。 ...

一个草根敲键盘的故事 1566

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

C++模板显式实例化实战:如何用.cpp文件隐藏实现细节(附完整代码示例)

本文深入探讨了C++模板显式实例化的工程实践,指导开发者如何将模板实现从.h头文件移至.cpp源文件,从而有效隐藏实现细节、提升编译速度并强化代码封装。通过完整的代码示例,详细解析了类模板、函数模板的分离步骤,并对比了显式实例化与显式具体化的核心区别,为构建更高效、更安全的C++库提供了实用方案。

hp777的博客 200

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C++模板编程:显式实例化与显式具体化的核心区别与应用

C++模板是泛型编程的核心机制,它允许编写与类型无关的通用代码,通过编译器在编译期根据具体类型生成特化版本,实现代码复用与类型安全。其原理基于“惰性实例化”和“包含模型”,编译器在遇到模板使用时才会根据模板定义生成具体代码。这一机制的技术价值在于提升代码的抽象能力与复用性,但同时也带来了编译时间增加和符号管理复杂性等挑战。在实际工程中,模板广泛应用于容器库、算法库及元编程等场景。针对模板编译与链接的常见问题,如“undefined reference”错误,C++提供了显式实例化与显式具体化两种高级特性进行

weixin_31364787的博客 347

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

C++成员函数模板显式实例化:解决分离编译与优化工程实践

C++模板作为编译期多态的核心机制,通过泛型编程实现了代码的高度复用。其工作原理是编译器根据具体类型参数在编译阶段生成特化代码,这带来了灵活性,但也面临编译膨胀和实现暴露的挑战。为了解决大型项目中模板代码全部放入头文件导致的编译时间增长和封装性破坏,C++提供了显式实例化技术。该技术允许开发者为特定的模板参数组合预生成代码实体,将模板定义移入源文件,从而优化编译速度并管理代码可见性。在涉及成员函数模板的场景中,由于嵌套的泛型特性,需要特别注意声明与定义的匹配,以及通过显式实例化指令为类模板和成员函数模板的特

weixin_34175509的博客 407

C++函数模板深度解析:从隐式实例化到显式具体化的实战指南

泛型编程是提升代码复用性和维护性的核心技术,其核心思想在于编写独立于数据类型的算法逻辑。函数模板作为实现泛型编程的关键机制,通过在编译期生成特定类型的代码,确保了类型安全且无损运行时性能。理解模板的实例化过程——尤其是隐式实例化与显式实例化的区别——对于控制编译行为和优化大型项目至关重要。当通用模板无法满足特定类型的需求时,显式具体化技术允许开发者为其定制特殊实现,这在与C风格字符串等特殊类型交互时尤为实用。本文结合工程实践,深入探讨了模板的匹配规则、分离编译的挑战以及利用SFINAE、constexpr等

weixin_30703911的博客 343

别再混淆了!图解C++模板显式实例化与显式具体化的5个关键区别

本文通过图解和代码示例,清晰解析了C++模板编程中显式实例化与显式具体化的五大核心区别。显式实例化用于提前生成代码以优化编译和隐藏实现,而显式具体化则为特定类型提供完全不同的定制实现。文章深入探讨了二者在编译链接、代码复用、语法细节及实战场景中的不同应用,帮助开发者避免混淆,写出更高效的C++代码。

cola5的博客 232

C++模板进阶:成员函数模板、显式实例化与声明实战指南

C++模板是泛型编程的核心机制,它通过参数化类型实现了代码的通用性。其原理是在编译期根据具体类型生成特化代码,从而在保证类型安全的同时提升代码复用率。这项技术的核心价值在于构建高度可复用的组件库,如STL容器和算法。在实际工程中,模板被广泛应用于基础设施开发、高性能计算和游戏引擎等领域。然而,随着项目规模扩大,隐式实例化可能导致编译时间膨胀和链接问题。为此,C++提供了成员函数模板、模板显式实例化和模板声明等进阶特性。成员函数模板允许类中的单个方法独立泛型,常用于实现智能指针的类型转换构造函数。模板显式实例

weixin_34195546的博客 380

Cpp入门基础

定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中 即为命名空间的成员。命名空间中可以定义变量/函数/类型等。namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量,所以下 ⾯的rand不在冲突了。C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/ 类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。

2401_86658278的博客 5159

C++成员函数模板显式实例化:原理、实践与编译优化

在C++模板编程中,模板实例化是编译器根据模板定义生成具体类型或函数代码的过程。其核心原理在于编译器在遇到模板使用时,会依据模板参数推导生成特化版本。这项技术的核心价值在于优化编译性能、控制代码生成粒度,并解决跨翻译单元的符号一致性问题。在大型工程和库开发的应用场景中,隐式实例化可能导致编译时间膨胀和跨DLL边界问题。通过引入显式实例化与extern声明机制,开发者可以精确控制模板代码的生成位置,将常用特化集中在单一编译单元,从而显著提升编译效率并确保二进制兼容性。本文聚焦于C++成员函数模板的实例化控制,

weixin_32466193的博客 287

C++模板编译模型解析:包含模型、显式实例化与C++20模块实践

C++模板是泛型编程的核心机制,它通过类型参数化实现了代码复用。其编译模型基于“蓝图”原理,编译器在模板实例化时需要看到完整定义才能生成具体类型的代码。这一特性带来了显著的工程价值:既能创建高度通用的数据结构和算法,又能保证类型安全。在应用场景中,开发者常面临代码组织与编译效率的权衡。本文聚焦于C++类模板和函数模板的几种主流写法,深入探讨包含模型如何通过头文件整合解决链接错误,以及显式实例化策略在特定场景下如何优化编译速度。随着C++20模块的引入,模板代码组织迎来了更优雅高效的解决方案,为大型项目提供了

weixin_30800987的博客 323
上一篇: 女生一定要看,男生看完转告你的女性朋友
下一篇: C++程序员必需的修养
0x16
博客等级 码龄20年 79粉丝 50原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值