In an attempt to revise C++ programming I have found something that is concerning me. Please consider this small example program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include <iostream>
usingnamespace std;
int add(short x, short y);
int main(){
double a = 5.5;
double b = 10.15;
add(a,b);
}
int add(short x, short y){
return x+y;
}
The above program compiles perfectly in GCC(G++)
Because a double is a totally different type to a short I would have thought that the compiler should generate a compile time error. Maybe it's just me, but I see this as a potential route to difficult to fix bugs.
Would somebody please explain why this program compiles? Are there any switches on GCC which will turn on additional type checking?
Most intrinsic (built in) data types can be implicitly cast (what your doing above) to one another.
I don't know about GCC flags so I'll let someone else have a crack at that, but you would need something to turn off implicit casting. One solultion would be to declare the function as explicit.
I.e: explicitint add(short x, short y);
Maybe it's just me, but I see this as a potential route to difficult to fix bugs.
It isn't. If you're trying to pass a fraction to a function that only accepts integers and it is actually crucial for the logic of your program that the number is not truncated, then you generally have a conceptual error and likely misunderstood the purpose of the function. And since people usually do not call functions they don't know anything about, it's not a problem.
To take your example with add, it's just either badly named (should be add_short or similar) or badly designed (should be a template).
I can't remember ever encountering a bug in my own software that was caused by unwanted truncation, nor can I remember any post in this or any other C++ forum where someone had a problem due to accidental truncation of a floating point number.
@Mathhead200: explicit can only be applied to constructors. Even if it were a constructor, it only takes effect on constructors with a single parameter.
There's no way to stop implicit type-casting, unless the compiler has a flag that disables such behaviour. You could create your own wrapper for each basic type, but that would take a bit of time. For example:
This software was written in Ada which is type fanatic. So for sure the engineers would have had to put in specific type casting. The problem was that the value was just too large and Ada threw an exception.
Ironically, the system involved in this error was not actually needed during flight, it was used to set up the rocket on the launch pad and was kept running 'just in case'. The uncaught exception brought the whole system down.
The automatic conversion of inbuilt types in C++ is a quirk, inherited from C but does not usually cause problems since all C++ programmers are aware of this quirk.
Java also has quirks in this area, notably inbuilt types have value semantics whereas user defined types have reference semantics. I believe the in built types are not derived from Object? and so you have to use wrapped versions if you want to store them in containers?
> I would have thought that the compiler should generate a compile time error. Maybe it's just
> me, but I see this as a potential route to difficult to fix bugs.
1 2 3 4 5 6 7 8 9 10 11 12
int add(short x, short y);
int main(){
double a = 5.5;
double b = 10.15;
// C++11: placing braces around an expression {expression}
// inhibits narrowing conversions of the expression
add( {a}, {b} ) ; // error: narrowing conversion of a from 'double' to 'short'
// error: narrowing conversion of b from 'double' to 'short'
}
#include <iostream>
int add(short x, short y);
int add(int x, int y);
int main(){
double a = 5.1;
double b = 10.15;
add(a,b);
}
int add(short x, short y){
return x+y;
}
int add(int x, int y){
return x+y;
}