考虑以下代码
#include <iostream>
using namespace std;
class MyClass{
int a;
public:
MyClass(int j) {a = j;}
int geta(void) {return a;}
};
int main(void)
{
MyClass ob = 99;
cout << ob.geta();
}
此代码的输出为99 我的问题是以下语句MyClass ob是声明类MyClass的对象,并且允许这种声明对象等于某个数字吗?也许更具体的声明是MyClass ob(99)你觉得怎么样?
答案 0 :(得分:3)
你提供了构造函数的int。如果没有explicit
关键字,则可以隐式调用它 - 就像这里一样。如果你要写MyClass ob(99)
,你会明确地调用这个构造函数。在将构造函数声明为explicit
之前没有区别。尝试使用显式构造函数将int分配给对象时,会出现编译错误。
编辑:我检查过 - 它正在使用复制构造函数,正如David和Alien01所说。只是Visual Studio不符合标准。
答案 1 :(得分:2)
创建像
这样的对象时MyClass ob =99 ;
你基本上是在调用类的构造函数。
当对象创建为
时,同样适用MyClass ob(99);
在这种情况下,也会调用类的构造函数。
答案 2 :(得分:2)
这是有趣的部分:
MyClass(int j) {a = j;}
默认情况下,具有单个参数的构造函数是隐式的,这意味着编译器会自动将其调用到您希望分配int
的位置{。}}。
如果您不希望您的类出现此行为,只需将构造函数更改为
即可MyClass
行为消失了,现在你需要显式(因此关键字)每次调用构造函数。请注意, explicit MyClass(int j) {a = j;}
关键字应仅出现在类主体的声明中,而不应出现在主体外部的实现中。
P.S。:例如,这是explicit
在预期后者时自动成为const char*
的方式。
答案 3 :(得分:1)
其他人已经提供了一般性答案,包括@ x13n。我将尝试对代码的真正含义提供更详细的解释。
语法MyObject ob = anotherMyObject;
相当于MyObject obj( anotherMyObject );
。含义是来自对象ob
的复制构造anotherMyObject
。编译器将始终匹配MyObject ob = ...;
与复制构造函数的调用(通常为MyObject( MyObject const &)
,但如果用户声明为MyObject( MyObject& )
,也可以是MyObject
。
在您的特定代码中,右侧不是MyObject
,因此它不能作为参数传递给复制构造函数,编译器会尝试将该rhs转换为可以与复制int
的构造函数应用一般规则。在您的情况下,有一个隐式构造函数接受MyObject
参数,并且可以用于创建临时MyObject ob( MyObject( 99 ) );
// ^^^ temporary created by the compiler to match the copy constructor
,因此编译器会将您的代码重写为:
MyObject ob(99)
请注意,这与int
不同,而是explicit
和复制构造函数的组合,即使整体效果相似。如果采用整数的构造函数声明为ob
,则编译器无法使用它来提供转换,代码将无法编译。
在对另一个答案的评论中,@ x13n指出这不是对复制构造函数的调用,就像向该构造函数添加跟踪一样,将不会生成跟踪。这是一个完全不同的问题,编译器能够通过在MyObject ob( MyObject(99) )
完全相同的地址中创建临时来优化副本。有两种方法可以验证,这两种方式都取决于编译器可以忽略副本的事实,它必须遵守相同的限制。因此,我们可以通过两种方式使class test1 {
test1( test1 const & ) {} // make the copy constructor private
public:
test1( int ) {}
};
class test2 {
public:
test2( test2 & ) {} // make the copy constructor take a non-const reference
// i.e. disable the use of temporaries
test2( int ) {}
};
int main() {
test1 t1 = 99; // copy constructor is private in this context
test2 t2 = 99; // g++: no matching function call to test2::test2(test2)
// diagnostics will differ with other compilers
}
无效,要么禁用对复制构造函数的访问,要么禁用对临时构造函数的调用:
{{1}}