1

I've been writing c for several years, just get into c++ for some needs! My book is C++ Primer 5/e, and I've reach the topic about constructor conversion and got some problems

In C++ we have many kinds of casting. like static_cast, dynamic_cast, and we also have function-like casting which is a kind of explicit casting.

class Sales_data{
public:
    //C++11 feature,ask compiler to create a default constructor for us
    Sales_data() = default;
    Sales_data(const std::string &s, unsigned n, double p):
        bookNo(s), units_sold(n), revenue(p*n);
    explicit Sales_data(const std::string &s): bookNo(s){}
    explicit Sales_data(std::istream&);

    Sales_data combine(const Sales_data &item);
private:
    std::string bookNo;      // implicitly initialized to the empty string
    unsigned units_sold;
    double revenue;
};

std::string s is an ISBN. and the forth one read a ISBN from stdin

I know without explicit, the following statements is legal.

item.combine(string("ISBN NUMBER"));
item.combine(cin);

//error: need two conversion const char *->temporary string-> temporary Sales_item
item.combine("ISBN NUMBER");

I just don't get what are the benefits of making the last two of the constructors explicit?

http://www.cplusplus.com/reference/vector/vector/vector/

I can't get the point why some of vector's constructors are declared explicit?? What is the reason?

Tim Hsu
  • 402
  • 5
  • 19
  • 2
    Em because it's really strange that when one says `do_something(5)` they means passing a vector with 5 elements? – kennytm Apr 14 '13 at 07:03
  • Neither of your "legal" statements are legal because you can't bind a temporary to a non-const `Sales_data` reference in `combine()`. – chris Apr 14 '13 at 07:04
  • @chris They both look legal to me ... the first passes a temporary to a const-ref, and the second pass a non-temporary (cin) by reference. – maditya Apr 14 '13 at 07:06
  • @maditya, `combine()` takes a non-const reference, which is being filled with those temporaries constructed in the function calls. – chris Apr 14 '13 at 07:07
  • @chris Wow, my bad ... I was looking at the constructors, not noticing that you were referring to `combine`. – maditya Apr 14 '13 at 07:10
  • @TimHsu if you're asking what the `explicit` keyword does, take a look at http://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-in-c-mean – maditya Apr 14 '13 at 07:11
  • @maditya, I actually had that comment up before, but I did that same thing as well and couldn't believe how crazy I was becoming. It's pi A.M. right now. – chris Apr 14 '13 at 07:14
  • chris is right, it's my mistake! – Tim Hsu Apr 14 '13 at 07:51

1 Answers1

3

explicit forbids to call the constructor to do the automatic conversion. The constructor can still be used as a normal constructor. Yes, the language should have been designed to have explicit constructors by default and annotate (implicit?) the conversion constructors... but that's how the story goes.

The reason that std::vector<T>::vector(int) is marked as explicit, for example is to forbid the following code:

void do_fancy_stuff(const std::vector<std::string> &data);

do_fancy_stuff(20);

If the vector constructor is not explicit it will be used to convert the int to a vector of 20 empty strings, and that makes little sense.

The general idea when writing a constructor TypeA::TypeA(TypeB x) is to wonder: "is this constructor converting the TypeB into a TypeA or is it just using x as a single parameter? If it is the latter, add explicit.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • Thanks @rodrigo, is it possible to discover the problem like this everytime we design our class? – Tim Hsu Apr 14 '13 at 07:56
  • 2
    @TimHsu: Well, look for any constructor that can be called with exactly one parameter and think: "is this a conversion operator"? If "yes" do nothing; if "no" add `explicit`. If in doubt, just add it. – rodrigo Apr 14 '13 at 09:45