【C++言語入門】 第19回 修飾子-続き
const
とnoexcept
以外の 修飾子 か?
override
やfinal
とかのキーワードですわね
override
override
についてお話ししますわね
override
?
override
は、メソッドをオーバーライドしていることを示す 修飾子 ですわ
override
を付加しますわ
virtual 型 メソッド名(引数...) override { 処理 };
override
を付加しますわ
override
を付加するとどうなるのだ?
noexcept
と異なるのだ
const
やnoexcept
と併用する場合には、const noexcept override
の順番で記述しますわ
virtual
が付加されていなければならないと云うことか...
override
を付加してみましょう
#pragma once
#ifndef FIGURE_H
#define FIGURE_H
class Figure {
int border_width_;
unsigned int color_;
public:
Figure(int border_width, unsigned int color)
: border_width_(border_width), color_(color) {}
virtual ~Figure() {}
int BorderWidth() { return border_width_; }
void BorderWidth(int border_width) { border_width_ = border_width; }
unsigned int Color() { return color_; }
void Color(unsigned int color) { color_ = color; }
virtual double Area() const noexcept = 0;
};
#endif // FIGURE_H
#pragma once
#ifndef CIRCLE_H
#define CIRCLE_H
#include <iostream>
#include "figure.h"
const double kPI = 3.14159265358979323846;
/// @brief 円
class Circle: public Figure {
double diameter_; // 直径
public:
Circle(double diameter) : Figure(1, 0xFF000000), diameter_(diameter) {}
virtual ~Circle() {};
double Diameter() const { return diameter_; }
void Diameter(double diameter) { diameter_ = diameter; }
virtual double Area() const noexcept override;
};
#endif // CIRCLE_H
double Circle::Area() const noexcept {
double radius = Diameter() / 2.0;
double a = radius * radius * kPI;
return a;
}
#include <iostream>
#include "circle.h"
int main(int argc, char* argv[]) {
Circle c(10.0);
std::cout << "円の直径は" << c.Diameter() << "cmです。" << std::endl;
std::cout << "円の境界線の幅は" << c.BorderWidth() << "mmです。" << std::endl;
std::cout << "円の面積は" << c.Area() << "cm^2です。" << std::endl;
return 0;
}
Figure
クラスのArea
メソッドは 純粋仮想関数 として宣言していますわ
const
およびnoexcept
の後に= 0
が付加されているのだ
Circle
クラスでArea
メソッドをオーバーライドしていますわ
override
が付加されているのだ
Area
メソッドの定義についてはoverride
を付加していないことに注意ですわ
overrideの目的
override
を付加することで、何かメリットがあるのか?
override
はnoexcept
と同様に、メソッドの動作に影響を与える 修飾子 ではありませんわ
override
を付加するのだ?
virtual
が付加されていない場合には、コンパイラがエラー、もしくは警告を出力してくれますわ
Figure
クラスのArea
メソッドをCircle
クラスでAres
メソッドとしてオーバーライド?してしまうとか...
override
については、積極的に使うようにしましょう
final
final
ですわね
final
?
final
は、派生クラスでメソッドをオーバーライドすることを禁止しますわ
final
を付加しますわ
virtual 型 メソッド名(引数...) final { 処理 };
final
を付加しますわ
final
を付加するとどうなるのだ?
override
と同じなのだ
const
やnoexcept
と併用する場合には、const noexcept final
の順番で記述しますわ
override
とfinal
については、どうなのだ?
final
を付加してみましょう
#pragma once
#ifndef CIRCLE_H
#define CIRCLE_H
#include <iostream>
#include "figure.h"
const double kPI = 3.14159265358979323846;
/// @brief 円
class Circle: public Figure {
double diameter_; // 直径
public:
Circle(double diameter) : Figure(1, 0xFF000000), diameter_(diameter) {}
virtual ~Circle() {};
double Diameter() const { return diameter_; }
void Diameter(double diameter) { diameter_ = diameter; }
virtual double Area() const noexcept override final;
};
#endif // CIRCLE_H
Circle
クラスのArea
メソッドにfinal
を付加してみました。
Circle
クラスを継承しているクラスがありませんので、final
の効果はありませんわね
Figure
クラスのArea
メソッドにfinal
を付加してみますわ
#pragma once
#ifndef FIGURE_H
#define FIGURE_H
class Figure {
int border_width_;
unsigned int color_;
public:
Figure(int border_width, unsigned int color)
: border_width_(border_width), color_(color) {}
virtual ~Figure() {}
int BorderWidth() { return border_width_; }
void BorderWidth(int border_width) { border_width_ = border_width; }
unsigned int Color() { return color_; }
void Color(unsigned int color) { color_ = color; }
virtual double Area() const noexcept final { return 0.0; }
};
#endif // FIGURE_H
#pragma once
#ifndef CIRCLE_H
#define CIRCLE_H
#include <iostream>
#include "figure.h"
const double kPI = 3.14159265358979323846;
/// @brief 円
class Circle: public Figure {
double diameter_; // 直径
public:
Circle(double diameter) : Figure(1, 0xFF000000), diameter_(diameter) {}
~Circle() {};
double Diameter() const { return diameter_; }
void Diameter(double diameter) { diameter_ = diameter; }
virtual double Area() const noexcept override;
};
#endif // CIRCLE_H
final
を付加する意味がありませんので、0.0を返すメソッドに変更していますわ
final
でオーバーライドを禁止するのは意味不明なのだ
Circle
クラスのArea
メソッドでオーバーライドした部分でエラーが発生していますわ
Circle
クラスのArea
メソッドのfinal
は消しているのだ
クラスにfinal
final
はメソッドだけではなく、クラスに対しても付加することが可能ですわ
final
を付加しますわ
class クラス名 final : public 基底クラス名 { クラス定義 };
final
を付加すると、クラスの継承自体が禁止されますわ
Figure
クラスにfinal
を付加してみましょう
#pragma once
#ifndef FIGURE_H
#define FIGURE_H
class Figure final {
int border_width_;
unsigned int color_;
public:
Figure(int border_width, unsigned int color)
: border_width_(border_width), color_(color) {}
virtual ~Figure() {}
int BorderWidth() { return border_width_; }
void BorderWidth(int border_width) { border_width_ = border_width; }
unsigned int Color() { return color_; }
void Color(unsigned int color) { color_ = color; }
virtual double Area() const noexcept { return 0.0; }
};
#endif // FIGURE_H
final
を付加し、Area
メソッドからfinal
を削除していますわ
Circle
クラスの継承部分がエラーとなっていますわ
finalの目的
final
を付加するメリットがあるのか?
final
はoverride
やnoexcept
と同様に、メソッドの動作に影響を与える 修飾子 ではありませんわ
final
を付加するのだ?
final
は基本的にヘッダーファイルにのみ記述されますわ
final
を削除してしまえばオーバーライドできてしまいますわ
final
は、余程の明確な意図がある場合以外は、使用を控えるべきですわ
final
を付加されたクラスやメソッドは、作者が絶対に継承やオーバーライドして欲しくないと考えていることを理解すべきですわね
Discussion