The compiler is allowed to make one implicit conversion to resolve the parameters to a function. What this means is that the compiler can use constructors callable with a single parameter to convert from one type to another in order to get the right type for a parameter.
Here's an example class with a constructor that can be used for implicit conversions:
class Foo
{
public:
// single parameter constructor, can be used as an implicit conversion
Foo (int foo) : m_foo (foo)
{
}
int GetFoo () { return m_foo; }
private:
int m_foo;
};
Here's a simple function that takes a Foo
object:
void DoBar (Foo foo)
{
int i = foo.GetFoo ();
}
and here's where the DoBar
function is called:
int main ()
{
DoBar (42);
}
The argument is not a Foo
object, but an int
. However, there exists a constructor for Foo
that takes an int
so this constructor can be used to convert the parameter to the correct type.
The compiler is allowed to do this once for each parameter.
Prefixing the explicit
keyword to the constructor prevents the compiler from using that constructor for implicit conversions. Adding it to the above class will create a compiler error at the function call DoBar (42)
. It is now necessary to call for conversion explicitly with DoBar (Foo (42))
The reason you might want to do this is to avoid accidental construction that can hide bugs.
Contrived example:
- You have a
MyString
class with a constructor that constructs a string of the given size. You have a function print(const MyString&)
(as well as an overload print (char *string)
), and you call print(3)
(when you actually intended to call print("3")
). You expect it to print "3", but it prints an empty string of length 3 instead.
The C++ standard does not specify the size of integral types in bytes, but it specifies minimum ranges they must be able to hold. You can infer minimum size in bits from the required range. You can infer minimum size in bytes from that and the value of the CHAR_BIT
macro that defines the number of bits in a byte. In all but the most obscure platforms it's 8, and it can't be less than 8.
One additional constraint for char
is that its size is always 1 byte, or CHAR_BIT
bits (hence the name). This is stated explicitly in the standard.
The C standard is a normative reference for the C++ standard, so even though it doesn't state these requirements explicitly, C++ requires the minimum ranges required by the C standard (page 22), which are the same as those from Data Type Ranges on MSDN:
signed char
: -127 to 127 (note, not -128 to 127; this accommodates 1's-complement and sign-and-magnitude platforms)
unsigned char
: 0 to 255
- "plain"
char
: same range as signed char
or unsigned char
, implementation-defined
signed short
: -32767 to 32767
unsigned short
: 0 to 65535
signed int
: -32767 to 32767
unsigned int
: 0 to 65535
signed long
: -2147483647 to 2147483647
unsigned long
: 0 to 4294967295
signed long long
: -9223372036854775807 to 9223372036854775807
unsigned long long
: 0 to 18446744073709551615
A C++ (or C) implementation can define the size of a type in bytes sizeof(type)
to any value, as long as
- the expression
sizeof(type) * CHAR_BIT
evaluates to a number of bits high enough to contain required ranges, and
- the ordering of type is still valid (e.g.
sizeof(int) <= sizeof(long)
).
Putting this all together, we are guaranteed that:
char
, signed char
, and unsigned char
are at least 8 bits
signed short
, unsigned short
, signed int
, and unsigned int
are at least 16 bits
signed long
and unsigned long
are at least 32 bits
signed long long
and unsigned long long
are at least 64 bits
No guarantee is made about the size of float
or double
except that double
provides at least as much precision as float
.
The actual implementation-specific ranges can be found in <limits.h>
header in C, or <climits>
in C++ (or even better, templated std::numeric_limits
in <limits>
header).
For example, this is how you will find maximum range for int
:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
Best Answer
Unless you use a clipping region set up to exclude the client area, you can paint over it from
OnNcPaint()
. So... if your drawing logic can't be modified to exclude the client in some other way, set up an appropriate clipping region first: