Methods¶
Objects - Data and Methods¶
C
Object ⇔
struct
Operations on objects: free functions
⟶ can be defined anywhere
struct point p = {1,2}; point_move(&p, 3, 4); // <--- not syntactically *bound* to p
C++
Classes: data and methods
Methods: functions bound to objects
point p{1,2}; p.move(3,4);
class point
Again¶
Reiterating class point
from
Classes and Objects:
What is a point? ⟶
x
andy
What is the responsibility of a point?
contain
x
andy
move itself
compute its distance to origin
… or from another point …
Access Methods (“Getters”) WRONG¶
Members are private ⟶ outside access prohibited
Read-only access desired, though
⟶ Public access methods
#pragma once class point { public: point() = default; // <-- generates default ctor ... point(int x, int y) : _x(x), _y(y) {} int x() { return _x; } // <-- WRONG! int y() { return _y; } // <-- WRONG! private: int _x{}; // <-- ... with these default values int _y{}; // <-- ... };
Getting
x
andy
values: call getters#include "point.h" #include <iostream> int main() { point p{2, 4}; std::cout << '(' << p.x() << ',' << p.y() << ")\n"; return 0; }
Access Methods (“Getters”): const
Objects¶
const
objects: must not be changed⟶ guarantee, enforced by the compiler
#include "point.h"
#include <iostream>
int main()
{
const point p{2, 4}; // <-- note **const**!
std::cout << '(' << p.x() << ',' << p.y() << ")\n";
return 0;
}
.../main-error.cpp:8:28: error: passing ‘const point’ as ‘this’ argument discards qualifiers [-fpermissive]
8 | std::cout << '(' << p.x() << ',' << p.y() << ")\n";
| ~~~^~
Access Methods (“Getters”): const
Methods¶
const
objects can only be accessed withconst
method⟶ leave the object itself (
this
) unchanged
#pragma once
class point
{
public:
point() = default;
point(int x, int y) : _x(x), _y(y) {}
int x() const { return _x; } // <-- const
int y() const { return _y; } // <-- const
private:
int _x{};
int _y{};
};
Modifying Method (p.move(...)
)¶
“Point, move yourself by
x
andy
”Usage …
#include "point.h"
#include <iostream>
int main()
{
point p{2, 4};
p.move(1, 2);
std::cout << '(' << p.x() << ',' << p.y() << ")\n";
return 0;
}
Implementation (inline)
#pragma once
class point
{
public:
point() = default;
point(int x, int y) : _x(x), _y(y) {}
int x() const { return _x; }
int y() const { return _y; }
void move(int x, int y)
{
_x += x;
_y += y;
}
private:
int _x{};
int _y{};
};
Non-Inline Implementation¶
Implementation in header file is inline
⟶ code inserted at call site
⟶ large binary size (not for
move(x,y)
, but sure for larger methods)
#pragma once
class point
{
public:
point() = default;
point(int x, int y) : _x(x), _y(y) {}
int x() const { return _x; }
int y() const { return _y; }
void move(int x, int y); // <-- declaration
private:
int _x{};
int _y{};
};
#include "point.h"
void point::move(int x, int y) // <-- implementation
{
_x += x;
_y += y;
}
Overloading move()
⟶ Vector Addition¶
Why not use a
point
instance as a vector?⟶
move(point vec)
#pragma once
class point
{
public:
point() = default;
point(int x, int y) : _x(x), _y(y) {}
int x() const { return _x; }
int y() const { return _y; }
void move(int x, int y) { _x += x; _y += y; }
void move(point vec) { move(vec.x(), vec._y); } // <-- overload
private:
int _x{};
int _y{};
};
Moving const point
Objects?¶
#include "point.h"
#include <iostream>
int main()
{
const point p{2, 4}; // <-- move?
const point vec{1, 2};
p.move(vec);
std::cout << '(' << p.x() << ',' << p.y() << ")\n";
return 0;
}
.../main-error.cpp:8:11: error: passing ‘const point’ as ‘this’ argument discards qualifiers [-fpermissive]
8 | p.move(vec);
| ~~~~~~^~~~~
As above (accessors): cannot call non-
const
method onconst
object
#include "point.h"
#include <iostream>
int main()
{
point p{2, 4}; // <-- cannot be const
const point vec{1, 2}; // <-- can be const
p.move(vec);
std::cout << '(' << p.x() << ',' << p.y() << ")\n";
return 0;
}
Finally: point::distance()
¶
What we want …
distance from another point
distance from origin
⟶ overload
⟶
const
method (though Heisenberg says we always modify through measurement)
#include "point.h"
#include <iostream>
int main()
{
const point p{2, 4}; // <-- not altered
std::cout << "distance from origin: " << p.distance() << '\n';
std::cout << "distance from (1,2): "
<< p.distance(point(1,2)) // <-- nameless *temporary* object
<< '\n';
return 0;
}
#pragma once
#include <cmath>
class point
{
public:
point() = default;
point(int x, int y) : _x(x), _y(y) {}
int x() const { return _x; }
int y() const { return _y; }
void move(int x, int y) { _x += x; _y += y; }
void move(point vec) { move(vec.x(), vec._y); } // <-- overload
double distance(point other) const
{
return std::sqrt(
std::pow(std::fabs(_x - other._x), 2) +
std::pow(std::fabs(_y - other._y), 2)
);
}
double distance() const
{
return distance(point(0,0));
}
private:
int _x{};
int _y{};
};
const
Correctness vs. Pollution¶
const
pollution“being correct is very cumbersome”
not using
const
is arrogant (“the compiler cannot help me because I am better”)
Nice goodie offered by the language
Compiler helps me verify that my code is correct
const
correctness