final
¶final
specifier can be used on a class to disallow derived classesclass base {
public:
virtual void member() = 0;
};
class derived final : public base {
public:
void member() override;
};
class error : public derived { };
input_line_9:1:15: error: base 'derived' is marked 'final'
class error : derived { };
^
input_line_8:6:8: note: 'derived' declared here
class derived final : base {
^ ~~~~~
Interpreter Error:
final
specifier can also be used on a virtual
function to specify further overrides are not permittedclass derived2 : public base {
void member() final;
};
class error : public derived2 {
void member() override;
};
input_line_13:3:10: error: declaration of 'method' overrides a 'final' function
void method() override;
^
input_line_11:2:10: note: overridden virtual function is here
void method() final;
^
final
makes it clear to the reader that there are no derived classes or methodsfinal
makes it clear to the compiler, allowing devirtualization optimizationsoverride
¶override
ensures that the function overrides a virtual member functionclass derived3 : public base {
void member() const; // no error or warning
}
class derived4 : public base {
virtual void member() const; // no error or warning
}
class derived5 : public base {
void member() const override;
}
input_line_16:2:25: error: only virtual member functions can be marked 'override'
void member() const override;
^~~~~~~~
class example {
int _a = 42;
bool _b = false;
string _c = "Hello World!";
public:
friend inline ostream& operator<<(ostream& out, const example& x) {
return out << "(" << x._a << ", " << x._b << ", " << x._c << ")";
}
};
{
example x;
cout << x << endl;
}
class example2 {
int _a = 42;
bool _b = false;
string _c = "Hello World!";
public:
example2() = default;
example2(int a) : _a(a) { }
friend inline ostream& operator<<(ostream& out, const example2& x) {
return out << "(" << x._a << ", " << x._b << ", " << x._c << ")";
}
};
{
example2 x;
cout << x << endl;
example2 y(10);
cout << y << endl;
}
class example3 {
int _a = 42;
bool _b = false;
string _c = "Hello World!";
public:
example3(int a) : _a(a) { }
example3(double a) : example3(static_cast<int>(round(a))) { }
friend inline ostream& operator<<(ostream& out, const example3& x) {
return out << "(" << x._a << ", " << x._b << ", " << x._c << ")";
}
};
{
example3 x(42.8);
cout << x << endl;
}
class example4 : public example3 {
public:
string _d = "New Member";
using example3::example3;
};
{
example4 x(42.8);
cout << x << endl;
cout << x._d << endl;
}
class example5 : public example3 {
public:
using example3::example3;
example5(int a) : example3(a + 1) { }
};
{
example5 x(10);
cout << x << endl;
}
class example6 : public example3 {
public:
using example3::example3;
example6(int a) = delete;
};
{
example6 x(10);
cout << x << endl;
}
input_line_27:3:14: error: call to deleted constructor of 'example6'
example6 x(10);
^ ~~
input_line_26:4:5: note: 'example6' has been explicitly marked deleted here
example6(int a) = delete;
^
namespace bcc {
struct example7 {
static int x; // declaration
};
int example7::x = 5; // definition (don't put in a header!)
}
const static
members may be initialized directly in the classstruct example8 {
const static int x = 42;
};
(void)(cout << example8::x << endl); // not an odr-use
static
members may be declared inline
(C++17) and constexpr
inline static
members do not require a definition at namespace scopestruct example9 {
inline static int x = 42;
};
example9::x = 56;
constexpr static
members, like const static members, only require a namespace scope definition if odr-used (until C++17)struct example10 {
constexpr static int x = 42;
};
(void)(cout << example10::x << endl); // not an odr-use
constexpr
implies inline
for static
member variables(void)(cout << &example10::x << endl); // an odr-use
final
and override
as appropriatestatic
variables for static
member variablesfinal