Show Lecture.ExtensibleNotMutable as a slide show.
CS253 Extensible Not Mutable
Extensible, not mutable
- C++ is extensible, not mutable.
- extensible: you can extend the language. You can add functionality.
- mutable: you cannot change the language.
2+2
will always be 4
.
Extending
int main() {
string sin = "Impeached: ";
string all = sin + 17 + ' ' + 42 + ' ' + 45;
cout << all << '\n';
}
c.cc:3: error: no match for 'operator+' in 'sin + 17' (operand types are
'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} and 'int')
That failed, because you can’t use +
on a std::string
and an int
.
Extending
string operator+(const string &s, int n) {
return s + to_string(n);
}
int main() {
string sin = "Impeached: ";
string all = sin + 17 + ' ' + 42 + ' ' + 45;
cout << all << '\n';
}
Impeached: 17 42 45
Hooray! C++ is extensible! I extended the language to include
string + int
.
For all I know, there’s some obscure line of the C++ standard that
forbids overloading operators with all built-in and std::
operands.
More Extending
class Fraction {
int top, bot;
public:
Fraction(int num, int den) : top(num), bot(den) { }
double get() const { return top*1.0/bot; }
};
int main() {
Fraction f(355, 113);
cout << f << '\n';
}
c.cc:10: error: no match for 'operator<<' in 'std::cout << f' (operand types
are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'Fraction')
Of course, that failed. <<
has no idea what to do with
an ostream
(output stream) and a Fraction
.
More Extending
class Fraction {
int top, bot;
public:
Fraction(int num, int den) : top(num), bot(den) { }
double get() const { return top*1.0/bot; }
};
ostream & operator<<(ostream &os, const Fraction &f) {
os << f.get();
return os;
}
int main() {
Fraction f(355, 113);
cout << f << '\n';
}
3.14159
Hooray! I extended the language to include ostream << Fraction
.
Why the return os
in operator<<
?
More Extending
class Fraction {
int top, bot;
public:
Fraction(int num, int den) : top(num), bot(den) { }
double get() const { return top*1.0/bot; }
};
ostream & operator<<(ostream &os, const Fraction &f) {
return os << f.get();
}
int main() {
Fraction f(355, 113);
cout << f << '\n';
}
3.14159
operator<<
can simply return the result of <<
.
Why is operator<<
not a method of Fraction
?
How operators work
- For an operator to be a method of
class Fraction
, it must
take a Fraction
as its left-hand argument.
- It would only take a single explicit argument—the other, implicit,
left-hand argument would be
*
this
, the current object.
- In the case of
cout << f
, the left-hand argument is an ostream
.
- You can’t add methods to
class
ostream
.
- It’s not yours.
- That class is finished.
- Therefore, in this case,
operator<<
is not a method;
it is, instead, a free function.
Mutation
Consider this surprising result:
int main() {
char now[] = "01:56:46";
cout << now+3 << '\n';
}
56:46
now
is an array of char
.
- An array name (
now
) is the same as a pointer to the first element,
or a char *
.
- Adding
3
to a pointer moves it forward three items.
I don’t like this. I want it to simply append a "3"
to the string.
Let’s redefine it!
Futility
string operator+(char *p, int n) {
return p + to_string(n);
}
int main() {
char now[] = "01:56:46";
cout << now+3 << '\n';
}
c.cc:1: error: ‘std::string operator+(char*, int)’ must have an argument of
class or enumerated type
That failed. I can’t mutate the language. char * + int
is already
defined, and I can’t change it.
Besides, at least one of the arguments has to be a non-built-in type.
It wouldn’t work if I tried to define operator%(char *p, int n)