开发者

C++ Why is the converter constructor implicitly called?

开发者 https://www.devze.com 2022-12-23 04:32 出处:网络
Why is the Child class\'s converter constructor called in the code below? I mean, it automatically converts Base to Child via the Child converter constructor. The code below compiles, but shouldn\'t

Why is the Child class's converter constructor called in the code below?

I mean, it automatically converts Base to Child via the Child converter constructor. The code below compiles, but shouldn't it not compile since I haven't provided 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;
 开发者_Python百科 }
};

void main()
{
  Base  base;
  Child child;

  if(child != base)
    std::cout << "not equal";
  else
    std::cout << "equal";
}


The function with the signature Child(Base const& base_) is not a copy constructor (the right hand side type is not the same as the left's). That constructor can be used implicitly by the compiler to coerce one type into another for the purpose of the comparison you are making in main. To prevent this mark the constructor explicit.


Because you provided a conversion constructor. If you don't want the compiler to automatically convert Base objects to Child using the

Child(Base const& base_)

constructor, make it explicit:

explicit Child(Base const& base_)

This way, the constructor will only be called when you explicitly specify it, in contexts like:

Child ch(base);
foo(Child(base));
new Child(base);


Because Child cannot be compared to Base - it can only be compared to another Child. Thus, your compiler creates an implicit copy of Base to Child in order to cause the conversion. If you change your code to:

class Child : public Base
{
public:
  Child() {}
  explicit Child(Base const& base_) :
    Base(base_)
  {
    std::cout <<"should never called!";
  }
  bool operator!=(Child const&)
  {
    return true;
  }
};

You'll find that it no longer compiles.


Because you don't provide any operator!=() that take Base as argument : the compiler will try "what he can" and see that there is a conversion constructor to the argument type (Child) that can be called. So it use it to make the != work.

0

精彩评论

暂无评论...
验证码 换一张
取 消