Dummies question about "explicit"

B

Boltar

Hi

I though I knew what the explicit keyword did , but can someone
explain to me why the following code doesn't compile?

class foo
{
public:
explicit foo(int i) { }
};


main()
{
foo f(1);
foo g = 2; <--- error is here
}

I was always under the impression that the 2 types of initialisation
in main() were equivalent. Obviously not. Whats the difference?

B2003
 
D

DDD

Hi

I though I knew what the explicit keyword did , but can someone
explain to me why the following code doesn't compile?

class foo
{
public:
explicit foo(int i) { }

};

main()
{
foo f(1);
foo g = 2; <--- error is here

}

I was always under the impression that the 2 types of initialisation
in main() were equivalent. Obviously not. Whats the difference?

B2003

The following paragraphs come from <C++ Professional Programmer's
Handbook>
Explicit Constructors
A constructor that takes a single argument is, by default, an implicit
conversion operator, which converts its argument to an object of its
class . Examine the following concrete example:
class string
{
private:
int size;
int capacity;
char *buff;
public:
string();
string(int size); // constructor and implicit conversion operator
string(const char *); // constructor and implicit conversion operator
~string();
};
Class string has three constructors: a default constructor, a
constructor that takes int, and a constructor that
constructs a string from const char *. The second constructor is used
to create an empty string object with an
initial preallocated buffer at the specified size. However, in the
case of class string, the automatic conversion is
dubious. Converting an int into a string object doesn't make sense,
although this is exactly what this constructor does.

Consider the following:
int main()
{
string s = "hello"; //OK, convert a C-string into a string object
int ns = 0;
s = 1; // 1 oops, programmer intended to write ns = 1,
}
In the expression s= 1;, the programmer simply mistyped the name of
the variable ns, typing s instead. Normally,
the compiler detects the incompatible types and issues an error
message. However, before ruling it out, the compiler first
searches for a user-defined conversion that allows this expression;
indeed, it finds the constructor that takes int.
Consequently, the compiler interprets the expression s= 1; as if the
programmer had written
s = string(1);
You might encounter a similar problem when calling a function that
takes a string argument. The following example
can either be a cryptic coding style or simply a programmer's
typographical error. However, due to the implicit
conversion constructor of class string, it will pass unnoticed:
int f(string s);
int main()
{
f(1); // without a an explicit constructor,
//this call is expanded into: f ( string(1) );
//was that intentional or merely a programmer's typo?
}
'In order to avoid such implicit conversions, a constructor that takes
one argument needs to be declared explicit:
class string
{
//...
public:
explicit string(int size); // block implicit conversion
string(const char *); //implicit conversion
~string();
};
 
P

Pete Becker

foo f(1);
foo g = 2; <--- error is here

I was always under the impression that the 2 types of initialisation
in main() were equivalent. Obviously not. Whats the difference?

The difference is that the first one constructs an object of type foo,
initialized with the value 1. The second creates a temporary object of
type foo, initialized with the value 2, then copies the temporary to g.
The compiler is permitted to skip the copy and initialize g directly,
but only if the full form would be legal.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,517
Latest member
Andres38A1

Latest Threads

Top