C ++为什么隐式调用转换器构造函数?

时间:2010-03-15 23:33:08

标签: c++

为什么在下面的代码中调用了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";
}

4 个答案:

答案 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)的转换构造函数。所以用它来制作!=工作。