Lesson 10 | Constructors as Conversions |
Objective | Constructors can perform automatic conversions. |
C++ Constructors to perform automatic Conversions
Constructors with a single parameter are automatically conversion functions.
One reason C++ has implicit conversions for ADTs is that, according to OOP conventions, ADTs should have the look and feel of the native types.
Consider the following class, whose purpose is to print nonvisible characters with their ASCII designation; for example, the code 07 (octal) is alarm
or bel
.
//ASCII printable characters
class pr_char {
public:
pr_char(int i = 0) : c(i % 128) {}
void print() const { cout << rep[c]; }
private:
int c;
static char* rep[128];
};
char* pr_char::rep[128] = { "nul", "soh", "stx",
.....
"w", "x", "y", "z",""{", "|", "}", "~", "del" };
int main()
{
int i;
pr_char c;
for (i = 0; i < 128; ++i) {
c = i; //or: c = static_cast<pr_char>(i);
c.print();
cout << endl;
}
}
Passing Arguments to a Function
It is very important to understand precisely how arguments are passed to a function. This affects how you write functions and ultimately how they operate. There are also a number of pitfalls to be avoided. In general, the function
arguments should correspond in type and sequence with the list of parameters in the function definition. You have no latitude so far as the sequence is concerned, but you do have some flexibility in the argument types. If you specify
a function argument of a type that does not correspond to the parameter type, then the compiler inserts an implicit conversion of the argument to the type of the parameter where possible.
The rules for automatic conversions of this kind are the same as those for automatic conversions in an assignment statement. If an automatic conversion is not possible, you will get an error message from the compiler. There are two mechanisms by which arguments are passed to functions, pass-by-value and pass-by-reference.
The constructor creates an automatic conversion from integers to pr_char
. Notice, the c = i;
statement in the loop implies this conversion. It is also possible to explicitly use a cast.
Unneeded conversions produced by conversion constructors are a source of obscure runtime bugs.
Avoid this problem by using the keyword explicit
to preface a single-argument constructor.
This disables automatic conversion.