类构造函数参数传递方式及类内对象声明疑问
问题解答
1. 为什么第81行clsAddress Address("", "", "", "")无错误?
这是C++中**直接初始化(Direct Initialization)**的合法写法:当你用类名 对象名(参数列表)的形式声明对象时,编译器会直接调用匹配的构造函数(这里是接受四个字符串的构造函数)创建对象,只要类提供了对应的构造函数,这种写法就完全合规,不会触发编译错误。
2. 声明带参构造函数的对象时的规范
根据C++标准,初始化带参构造的对象有几种常用方式,各自有不同的适用场景和注意事项:
- 直接初始化:
类名 对象名(参数)
这是最基础的写法,直接调用构造函数创建对象,只要参数和构造函数签名匹配即可。但要注意在某些场景下可能产生歧义(比如clsAddress addr(10)可能被解析成函数声明)。 - 列表初始化(C++11+):
类名 对象名{参数}
这种写法更安全,能避免函数声明歧义,同时支持初始化聚合类型和非聚合类型,是C++11及以后推荐的写法之一。 - 拷贝初始化:
类名 对象名 = 类名(参数)
这种写法会先创建临时对象,再拷贝(或移动)到目标对象,但编译器通常会优化掉临时对象的创建(RVO)。如果构造函数被声明为explicit,这种写法会报错,因为explicit禁止隐式的拷贝初始化转换。
3. 类内与类外初始化的差异
你观察到的“类外两种方式有效,类内仅一种被接受”,核心原因是类内非静态成员的声明语法限制:
- 在类外(全局作用域或函数内),
类名 对象名(参数)是明确的对象初始化,编译器不会混淆为函数声明。 - 在类内声明非静态成员时,
clsAddress Address("", "", "", "")会被编译器解析为成员函数声明(返回clsAddress类型、名为Address、参数为四个字符串的函数),而非对象初始化。因此类内不能用()的方式初始化非静态成员。
类内初始化非静态成员,在C++11及以后可以用以下两种合法方式:- 拷贝初始化:
clsAddress Address = clsAddress("", "", "", ""); - 列表初始化:
clsAddress Address{"", "", "", ""};
而C++11之前,类内非静态成员只能在构造函数的初始化列表中完成初始化,无法在声明时就地初始化。
- 拷贝初始化:
内容的提问来源于stack exchange,提问作者Ziad Gad
相关产品推荐
相关产品推荐

