为什么在下面的代码中调用了Child类的转换器构造函数?
我的意思是,它会通过子转换器构造函数自动将Base转换为Child。下面的代码编译,但不应该不编译,因为我没有提供bool Child::operator!=(Base const&)
?
class Base
{
};
class Child : public Base
{
public:
Child() {}
Child(Base const& base_) :
Base(base_)
{
std::cout <<"should never called!";
}
bool operator!=(Child const&)
{
return true;
}
};
void main()
{
Base base;
Child child;
if(child != base)
std::cout << "not equal";
else
std::cout << "equal";
}
答案 0 :(得分:6)
签名为Child(Base const& base_)
的函数不是复制构造函数(右侧类型与左侧不同)。编译器可以隐式使用该构造函数将一种类型强制转换为另一种类型,以便在main
中进行比较。为了防止这种情况,请标记构造函数explicit
。
答案 1 :(得分:3)
因为您提供了转换构造函数。如果您不希望编译器使用
自动将Base
个对象转换为Child
Child(Base const& base_)
构造函数,明确指出:
explicit Child(Base const& base_)
这样,只有在显式指定构造函数时才会调用构造函数,例如:
Child ch(base);
foo(Child(base));
new Child(base);
答案 2 :(得分:1)
因为Child无法与Base比较 - 它只能与另一个Child进行比较。因此,您的编译器会创建Base to Child的隐式副本以进行转换。如果您将代码更改为:
class Child : public Base
{
public:
Child() {}
explicit Child(Base const& base_) :
Base(base_)
{
std::cout <<"should never called!";
}
bool operator!=(Child const&)
{
return true;
}
};
你会发现它不再编译。
答案 3 :(得分:0)
因为你没有提供任何以Base作为参数的运算符!=():编译器将尝试“他能做什么”并且看到有一个可以被调用的参数类型(Child)的转换构造函数。所以用它来制作!=工作。