为什么没有默认构造函数就无法编译?

2023-12-25

我可以做这个:

#include <iostream>

int counter;

int main()
{
    struct Boo
    {
        Boo(int num)
        {
            ++counter;
            if (rand() % num < 7) Boo(8);
        }
    };

    Boo(8);

    return 0;
}

这会编译得很好,我的计数器结果是21。但是当我尝试创建Boo对象传递构造函数参数而不是整数文字我收到编译错误:

#include <iostream>

int counter;

int main()
{
    struct Boo
    {
        Boo(int num)
        {
            ++counter;
            if (rand() % num < 7) Boo(num); // No default constructor 
                                            // exists for Boo
        }
    };

    Boo(8);

    return 0;
}

如何在第二个示例中调用默认构造函数而不是在第一个示例中调用默认构造函数?这是我在 Visual Studio 2017 上遇到的错误。

在在线 C++ 编译器 onlineGDB 上,我收到错误:

error: no matching function for call to ‘main()::Boo::Boo()’
    if (rand() % num < 7) Boo(num);

                           ^
note:   candidate expects 1 argument, 0 provided

Clang 给出以下警告消息:

<source>:12:16: warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'num' [-Wvexing-parse]
            Boo(num); // No default constructor 
               ^~~~~

这是一个最令人烦恼的解析问题。因为Boo是类类型的名称,并且num不是类型名称,Boo(num);可以是临时类型的构造Boo with num被争论Boo的构造函数或者它可以是一个声明Boo num;在声明符周围有额外的括号num(声明者可能总是有)。如果两者都是有效的解释,则标准要求编译器采用声明。

如果它被解析为声明,那么Boo num;将调用默认构造函数(不带参数的构造函数),该构造函数不是由您声明的,也不是隐式声明的(因为您声明了另一个构造函数)。因此该程序是格式错误的。

这不是问题Boo(8);, 因为8不能是变量的标识符(declarator-id),因此它被解析为创建变量的调用Boo暂时与8作为构造函数的参数,因此不会调用默认构造函数(未声明),而是调用您手动定义的构造函数。

您可以使用以下任一方法消除声明中的歧义:Boo{num};代替Boo(num);(因为{}不允许在声明符周围),通过将临时变量设为命名变量,例如Boo temp(num);,或者将其作为另一个表达式中的操作数,例如(Boo(num));, (void)Boo(num);, etc.

请注意,如果默认构造函数可用,则声明将是格式良好的,因为它位于if的分支块作用域而不是函数的块作用域,并且只会隐藏num在函数的参数列表中。

无论如何,滥用临时对象创建来进行正常(成员)函数调用似乎都不是一个好主意。

这种在括号中带有单个非类型名称的特殊类型的最令人烦恼的解析只能发生,因为目的是创建一个临时对象并立即丢弃它,或者如果目的是创建一个直接用作初始化程序的临时对象,例如Boo boo(Boo(num));(实际上声明了函数boo接受一个名为num与类型Boo并返回Boo).

通常不打算立即丢弃临时变量,并且可以使用大括号初始化或双括号来避免初始化程序情况(Boo boo{Boo(num)}, Boo boo(Boo{num}) or Boo boo((Boo(num)));, 但不是Boo boo(Boo((num)));).

If Boo不是类型名称,它不可能是声明,并且不会发生问题。

我还想强调一点Boo(8);正在创建一个新的临时类型Boo,甚至在类范围和构造函数定义内。正如人们可能错误地认为的那样,它不是使用调用者的构造函数来调用this与通常的非静态成员函数类似的指针。不可能在构造函数体内以这种方式调用另一个构造函数。这仅在构造函数的成员初始值设定项列表中可行。


即使声明由于缺少构造函数而格式不正确,也会发生这种情况,因为[stmt.ambig]/3 http://eel.is/c++draft/stmt.ambig#3:

消歧纯粹是句法上的;也就是说, 在这样的陈述中出现的名字,无论它们是否是 类型名称与否,通常不被使用或更改 消歧义。

[...]

消歧先于解析,并且作为声明消歧的语句可能是格式错误的声明。


在编辑中修复:我忽略了所讨论的声明与函数参数处于不同的范围,因此如果构造函数可用,则声明的格式良好。在任何情况下,消歧过程中都不考虑这一点。还对一些细节进行了扩展。

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

为什么没有默认构造函数就无法编译? 的相关文章

  • C# 静态类型不能用作参数

    public static void SendEmail String from String To String Subject String HTML String AttachmentPath null String Attachme
  • C# SmtpClient编程中如何设置带有中文的附件文件名?

    我的代码如下 ContentType ct new ContentType ct MediaType MediaTypeNames Application Octet ct Name 这是一个很长的中文文件名希望能用它在附件名中 Doc A
  • C#.Net 邮件将进入垃圾邮件文件夹

    我正在从 ASP net Web 应用程序发送电子邮件 邮件发送成功 没有失败 但大多数都进入了垃圾邮件文件夹 请帮助我克服垃圾邮件过滤器 我的发送邮件代码 public void SendMail string FromAddress s
  • 如何使用 openSSL 函数验证 PEM 证书的密钥长度

    如何验证以这种方式生成的 PEM 证书的密钥长度 openssl genrsa des3 out server key 1024 openssl req new key server key out server csr cp server
  • C# 中的 Stack<> 实现

    我最近一直在实现递归目录搜索实现 并且使用堆栈来跟踪路径元素 当我使用 string Join 连接路径元素时 我发现它们被颠倒了 当我调试该方法时 我查看了堆栈 发现堆栈内部数组中的元素本身是相反的 即最近 Push 的元素位于内部数组的
  • C# 中一次性对象克隆会导致内存泄漏吗?

    检查这个代码 class someclass IDisposable private Bitmap imageObject public void ImageCrop int X int Y int W int H imageObject
  • 混合模型优先和代码优先

    我们使用模型优先方法创建了一个 Web 应用程序 一名新开发人员进入该项目 并使用代码优先方法 使用数据库文件 创建了一个新的自定义模型 这 这是代码第一个数据库上下文 namespace WVITDB DAL public class D
  • 为什么这个 makefile 在“make clean”上执行目标

    这是我当前的 makefile CXX g CXXFLAGS Wall O3 LDFLAGS TARGET testcpp SRCS main cpp object cpp foo cpp OBJS SRCS cpp o DEPS SRCS
  • Makefile 和 .Mak 文件 + CodeBlocks 和 VStudio

    我对整个 makefile 概念有点陌生 所以我对此有一些疑问 我正在 Linux 中使用 CodeBlocks 创建一个项目 我使用一个名为 cbp2mak 的工具从 CodeBlocks 项目创建一个 make 文件 如果有人知道更好的
  • Unity手游触摸动作不扎实

    我的代码中有一种 错误 我只是找不到它发生的原因以及如何修复它 我是统一的初学者 甚至是统一的手机游戏的初学者 我使用触摸让玩家从一侧移动到另一侧 但问题是我希望玩家在手指从一侧滑动到另一侧时能够平滑移动 但我的代码还会将玩家移动到您点击的
  • Libev,如何将参数传递给相关回调

    我陷入了 libev 中争论的境地 通常 libev 在类似的函数中接收包 接收回调 没关系 但是实际操作中 我们需要派遣一个亲戚 写回调 根据收到的包裹处理具体工作 例如 S RECV MSG pstRecvMsg S RECV MSG
  • 如何在 Javascript 中连接 C# ActiveX 事件处理程序

    我尝试使用几个代码片段将 ActiveX 对象与 Javascript 事件处理程序挂钩 我无法确定为什么事件处理程序没有被调用 带有项目的 Github 存储库 https github com JesseKPhillips Csharp
  • 让网络摄像头在 OpenCV 中工作

    我正在尝试让我的网络摄像头在 Windows 7 64 位中的 OpenCV 版本 2 2 中捕获视频 但是 我遇到了一些困难 OpenCV 附带的示例二进制文件都无法检测到我的网络摄像头 最近我发现这篇文章表明答案在于重新编译一个文件 o
  • 如何从 Boost.PropertyTree 复制子树

    我有一些boost property tree ptree 我需要树来删除一些具有特定标签名称的元素 例如 xml 表示源ptree如下
  • .NET 和 Mono 之间的开发差异

    我正在研究 Mono 和 NET C 将来当项目开发时我们需要在 Linux 服务器上运行代码 此时我一直在研究 ASP NET MVC 和 Mono 我运行 Ubuntu 发行版 想要开发 Web 应用程序 其他一些开发人员使用 Wind
  • 如何编写一个接受 int 或 float 的 C 函数?

    我想用 C 语言创建一个扩展 Python 的函数 该函数可以接受 float 或 int 类型的输入 所以基本上 我想要f 5 and f 5 5 成为可接受的输入 我认为我不能使用if PyArg ParseTuple args i v
  • 如何获取带有某个属性注释的所有属性?

    我刚刚从 Roslyn 开始 我想找到所有用属性名称 OneToOne 注释的属性 我启动了 SyntaxVisualizer 并能够获取对该节点的引用 但我想知道是否有更简单的方法来实现此目的 这就是我所拥有的 var prop docu
  • 任何人都可以清楚地告诉如何在不使用像 这样的预定义函数的情况下找到带有小数值或小数值的指数吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 例如 2 0 5 1 414 所以想要 我是 c 的新手 所以请解释简单的逻辑 如果不是复杂的逻辑也足够了 在数学中 从整数取幂到实数
  • 从后面的代码添加外部 css 文件

    我有一个 CSS 文件 例如 SomeStyle css 我是否可以将此样式表文档从其代码隐藏应用到 aspx 页面 您可以将文字控件添加到标头控件中 Page Header Controls Add new System Web UI L
  • 如何在 C# 中获取 CMD/控制台编码

    我需要指定正确的代码页来使用 zip 库打包文件 正如我所见 我需要指定控制台编码 在我的例子中为 866 C Users User gt mode Status for device CON Lines 300 Columns 130 K

随机推荐

  • 保持 Android 表格中所有行的列对齐

    我在 Android 上遇到了一个问题 无论我尝试什么都无法解决 想象一个表格布局 有 3 个表格行 每行有两个文本字段 Image 由于新用户限制 无法在此处添加图像 http imgim com tbl behaviour png 现在
  • 基于 Zend Framework 的项目

    在哪里可以看到具有漂亮架构的 ZF bssed 项目 数据映射器 服务等 这是一些应用程序 http www framework zend com wiki pages viewpage action pageId 14134 http w
  • 如何在GAE上设置中级证书?

    我为我的自定义域购买了 SSL 认证 并设置了我的 GAE 项目 在新的 Firefox 版本发布之前 它在大多数浏览器上都运行良好 Firefox 拒绝了我的 SSL 认证 我使用过 SSL Checker 它给了我反馈 并非所有网络浏览
  • 用于计费协议的 Paypal Webhook 收到付款了吗?

    是否有在收到计费协议付款时触发的 Webhook 我创建了一个计费计划 并让用户接受每月定期付款的计费协议 当计费协议执行时 webhookBILLING SUBSCRIPTION CREATED fires 是否有一个 webhook 在
  • 对多个文件运行 Excel 宏

    我有一个 Excel 宏保存在一个空白工作簿和多个数据工作簿中 目前 我分别打开宏文件和每个数据文件 并使用键盘快捷键在每个文件上运行宏 有没有一种方法可以在所有数据工作簿上运行宏而无需打开它们 或者使用 一个批处理文件 VBA VBScr
  • Google 地图 - 获取区域/邻里的多边形边界

    我想在 Google Maps API v3 上进行简单搜索 并得到带有彩色多边形的地图 如下图所示 搜索 皮涅罗斯 圣保罗 我通过使用得到它维基地图 http WikiMapia org data 步骤是 Open 维基地图 http W
  • 如何仅列出两次提交之间更改的文件名

    我在存储库中有一堆提交 我想查看两次提交之间更改的文件列表 来自SHA1 to SHA2 我应该使用什么命令 git diff name only SHA1 SHA2 您只需要包含足够的 SHA 哈希来识别提交 SHA 的顺序并不重要 输出
  • 如何使用 BertForMaskedLM 或 BertModel 来计算句子的困惑度?

    我想使用 BertForMaskedLM 或 BertModel 来计算句子的困惑度 所以我编写了这样的代码 import numpy as np import torch import torch nn as nn from transf
  • 创建一个链接,可在任何设备上打开相应的地图应用程序,并提供前往目的地的路线

    我宁愿认为这并不难找到 但看起来像您所期望的那样 找到一篇很棒的跨设备文章并不容易 我想创建一个链接 打开移动设备的浏览器并浏览谷歌地图 或者打开地图应用程序 Apple 地图或谷歌地图 并直接开始路线 即 从当前位置开始 在给定点结束 纬
  • 使用 CouchDB 的 jquery.couch.js?

    Here http blog couchone com post 1027100082 whats new in couchdb 1 0 part 4 securityn stuff http blog couchone com post
  • org.hibernate.exception.SQLGrammarException:无法插入[com.sample.Person]

    我正在尝试建立一个我发现的 Hibernate 小型工作样本here http www mastertheboss com hibernate 182 hibernate tutorial html但是 当我运行代码时 出现以下错误 Exc
  • C# 中的验证框架?

    在java世界里有bean验证框架JSR 303 http download oracle com otndocs jcp bean validation 1 0 fr oth JSpec 这是一个经过深思熟虑的策略 用于在应用程序的表示层
  • 迭代数组并等待 Promise

    如何使用 Promises 迭代数据数组并返回数据 我已经看到了一些 Promise push asyncFunc 方法 但是我的数组中的一些条目将失败 因此根据我收集的信息 我无法使用它 var filesFromDisk 41679 4
  • 在 R 中查找某个范围内的值

    我的数据如下所示 我想选择大于 等于 35 且小于 等于 350 的值 我还想将这些值替换为withinrange value 1 35 36 37 350 355 3555 35555 要选择值 value value gt 35 val
  • Docker pull 给出了来自字节范围请求的预期 HTTP 206

    我在从我们的现场 proget 服务器提取 docker 镜像时遇到问题 这一直有效 但我已经离开它大约两个月了 我跑 docker pull proget docker myimage 几层已完成 拉取完成 但最大的一层给出了 来自字节范
  • 是否可以使用 DI 容器解析我的 ClaimsAuthorizationManager

    我已经让我的自定义 ClaimsAuthorizationManager 使用标准配置文件设置工作 但我想将业务层服务注入到我的实现中 但我无法弄清楚
  • Xcode 13 beta:“xcrun:错误:无法找到‘仪器’”

    请注意 我在找 Applications Xcode app Contents Developer usr bin instrumentsutil 小写 而不是Instruments应用程序可以在以下位置找到 Xcode app Conte
  • IEnumerable 和 IEnumerator

    谁能向我解释一下 IEnumerable 和 IEnumerator 之间有什么区别 以及如何使用它们 谢谢 一般来说 一个IEnumerable是一个可以枚举的对象 例如列表或数组 一个IEnumerator是一个存储枚举状态的对象 它们
  • 为什么函数中没有括号

    任何帮助或提示将不胜感激 为什么在方法调用中不使用括号 如果我使用括号 onInputChange 则在加载页面时会调用该方法 调用后 如果我在输入框中键入任何内容并单击 onInputChange 方法之外的区域 则不会调用该方法 如果我
  • 为什么没有默认构造函数就无法编译?

    我可以做这个 include