質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

6回答

6386閲覧

C++でclassにfinalを控えめに使うべき理由について

altzweel

総合スコア11

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

3クリップ

投稿2021/05/21 08:39

C++ Core Guidelinesを読んでいて納得できない部分があります。

C.139: Use final on classes sparinglyの項目です。

calssに対するfinalを控えめにするという項目で、理由として以下の様に書いてあります。

Reason Capping a hierarchy with final classes is rarely needed for logical reasons and can be damaging to the extensibility of a hierarchy.

  • 継承を禁止する論理的な理由があることはめったにない
  • クラスの拡張性を損なう

という内容かと思いますが、個人的には納得できませんでした。
constを推奨するのと同じような理由でfinalは積極的に使っていきたいように感じます。

この理由について掘り下げて議論している書籍、Webの情報などが知りたいです。
独自見解、他言語での状況などでも大丈夫です。

基本的には納得してCore Guidelinesに従いたいと思っているので、こうするべきとされている理由をより深く知りたいです。

よろしくおねがいします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2021/05/21 09:15

継承を禁止することによるメリットは何ですか?
altzweel

2021/05/24 03:47

自分で書いていると、基底クラスを継承したクラスはさらに継承されることを考えないので、禁止したほうが意図が明確で想定外のバグが減ると思いました。
Zuishin

2021/05/24 05:11

ふつうは継承を考えて作り、継承してはいけないものを明示的に final にするものだと思います。 基本的に継承しないという作り方が特殊なので、通常のガイドラインは適用できないかと。 final をつけるつけない以前に、クラスの作り方を見直すか、見直せないならそのガイドラインを受け入れないようにするかという選択になるのではないでしょうか。
guest

回答6

0

ベストアンサー

「C.139: Use final on classes sparingly」は字義通り「控え目に(sparingly)利用せよ」と言っているだけですから、クラス設計において意味論上の妥当な理由があると考えるならfinal修飾すればよいと思います。

#170: C153. Use final only sparingly を受けて、Bjarne Stroustrup氏が C.139: Use final sparinglyを追加 しています。当時はクラス/関数の両方を対象としていたようですが、後に #576: C.139 is harmful などを受けて Noteの追記クラスだけに対象を絞って います。

Reason
Capping a hierarchy with final is rarely needed for logical reasons and can be damaging to the extensibility of a hierarchy.

関連する技術記事として、下記のような主張もあります:

投稿2021/05/26 06:02

編集2021/05/26 06:32
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

https://github.com/isocpp/CppCoreGuidelines/issues/170
ここを見る限りビャーネ・ストラウストラップの著書で主張されてるとのことですが、日本語版を読む限りニュアンスが違うように思います。

 「性能向上のためfinalを用いる人もいる。......しかし、最適化を目的にして、むやみにfinalを利用してはいけない。クラス階層設計に影響する(多くの場合は悪影響を与える) 一方で性能向上が得られるのは、本当にまれだ。」 柴田 望洋 訳 プログラミング言語C++ 第4版

https://github.com/isocpp/CppCoreGuidelines/blob/1b79ede5c56be8371d7a66e02025d3e248271efb/CppCoreGuidelines.md#Rh-final

古い版ではメンバー関数についての記述もあるように、クラス宣言に限定せず最適化目的のfinalの濫用について問題にしているだけではないでしょうか。
つまり、オーバーライドや継承させないことを目的としていないfinalの使用は控えるべきだというのが本来の主張ではないかと思います。

上の議論含め、この方針に対してはfinalは積極的に用いるべきではないかという異論も多いです。
しかし、本来の主張が上記のようなものであるなら、デフォルトで継承させない方針の下でデフォルトでfinalを付けるというような使用法は、継承させないというfinalのセマンティックにあった使用法なので許されるはずです。
デフォルトで継承させない方針自体に反対しているのであれば継承させないことを目的としていてもfinalの使用を控えるべきという主張につながるかもしれませんが、継承されないことを前提としたクラス設計自体は認めています。

投稿2021/05/26 05:01

yudedako67

総合スコア2047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

「継承よりも委譲」が好まれるご時世を反映してるんじゃないかしら。
※ Javaでいうところの「extends より interface/implements」

もちろん「控えめに」であって 言語道断まかりならぬ ってことじゃない。
あるクラスが「継承されては困る/継承されることを想定していない」なら final 修飾すべきと考えます。
(constも同様の理由:「書き換えられては困る/書き換えられることを想定していない」ですし)

メンバ関数のfinalを「控えめに」とは言うてませんしね。

投稿2021/05/21 08:51

編集2021/05/21 10:20
episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

const推奨と言われるのは、constを使えば明らかなメリットがあるにも拘らず、付けない人が多いからです。また、いくらconst推奨と言っても、後から値を変更するつもりの変数にまでconstを付けろとまでは、言っていません。そんなことをしたら、そもそもコードを書けません。要するに変数の使い方次第です。

finalを控えめに、と言われるのは、finalを使ってもメリットがあるかどうか、わからないにも拘わらず、付ける人がいるからです(おそらく最適化を期待しているのでしょう)。その一方で、継承による拡張ができないというデメリットは、はっきりしています。もし、設計の意図として、継承できないデメリットが、実はメリットなのだ、ということが明確ならば、finalを付けるべきですし、ガイドラインもそれを否定していません。要するにクラスの使われ方次第です。

メタなレベルで考えると、どちらも同じことを言っています。変数・クラス・関数、どれも定義する前に、使い方・使われ方をしっかり考えろ、ということです。

投稿2021/05/26 19:58

Bearded-Ockham

総合スコア430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

あまり使わない機能ですが。

少なくともconst推奨とfinal推奨は同レベルではないと思います。constの場合は定数属性(値の書き換えが生じない)がコーディングの段階で確実だから使うわけです。言い換えれば、constは直接的な影響範囲が局所的で、コーディング時に影響範囲を把握しきることができるという前提で利用します。これができないならば(拡張性が後に課題となるならば)、最初からconstを利用できません。

一方、finalを使う場合はクラス設計に関する大局的ものであり、コーディング時に影響範囲を把握しきることは少ないはずです。これはプログラマではなく、プロマネ以上でないと判断できないはずであり、コーディングの段階でfinalを付与をするのは危険です。

投稿2021/05/26 06:37

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

あまり詳しくありませんが、面白そうな話題なので書いておきます。


おそらく、『オブジェクト指向の基本概念』の考えから来ているのではないかと思います。

データ(= メンバ変数)と処理(= メンバ関数)をひとまとめしたオブジェクトなるものを中心に見る考え方です。

ポリモフィズムと呼ばれるやつはこれを表現するためです。

finalを付けると、継承できないので、それが理由だと思いましたが。

投稿2021/05/21 09:11

編集2021/05/27 10:32
BeatStar

総合スコア4962

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2021/05/21 10:03

...それ継承じゃないから。
BeatStar

2021/05/21 10:30

本文ではインターフェースなので現象とは違いますが、本質的には同じでは? (親が継承を想定しているかどうか、、、だと思ったんですが) もし違うなら、後学のためにご教授お願いします。
fana

2021/05/21 10:51

質問がC++の話なので,例を別言語で示すよりもC++の物を書いた方が良いのではないでしょうか?
episteme

2021/05/21 11:50

interface は implements されるためものなんだから final云々の議論にすらならんでしょ。 (List<T> を implementsした) ArrayList<T> をfinalにすべきか否かって議論ならともかく。
BeatStar

2021/05/27 10:31

あ、確かにそうですね… 修正します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問