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 name = "Jack";
cout << name + 36782;
}
c.cc:3: error: no match for 'operator+' in 'name + 36782' (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 name = "Jack";
cout << name + 21825;
}
Jack21825
Hooray! C++ is extensible! I extended the language to include
string + int
.
More Extending
class Foo {
public:
Foo(int value) : n(value) { }
int get() const { return n; }
private:
int n;
};
int main() {
Foo f(42);
cout << "The foo is " << f << '\n';
}
c.cc:11: error: no match for 'operator<<' in 'std::operator<<
<std::char_traits<char> >(std::cout, ((const char*)"The foo is ")) << f'
(operand types are 'std::basic_ostream<char>' and 'Foo')
Of course, that failed. <<
has no idea what to do with
an ostream
(output stream) and a Foo
.
More Extending
class Foo {
public:
Foo(int value) : n(value) { }
int get() const { return n; }
private:
int n;
};
ostream & operator<<(ostream &os, const Foo &f) {
os << f.get();
return os;
}
int main() {
Foo f(42);
cout << "The foo is " << f << '\n';
}
The foo is 42
Hooray! I extended the language to include ostream << Foo
.
Why the return os
in operator<<
?
More Extending
class Foo {
public:
Foo(int value) : n(value) { }
int get() const { return n; }
private:
int n;
};
ostream & operator<<(ostream &os, const Foo &f) {
return os << f.get();
}
int main() {
Foo f(42);
cout << "The foo is " << f << '\n';
}
The foo is 42
operator<<
can simply return the result of <<
.
Why is operator<<
not a method of Foo
?
How operators work
- For an operator to be a method of
class Foo
, it must
take a Foo
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[] = "05:46:21";
cout << now+3 << '\n';
}
46:21
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[] = "05:46:21";
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)