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

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

ただいまの
回答率

88.59%

オーバーライド時のvirtual、override記述について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,096
退会済みユーザー

退会済みユーザー

前提・実現したいこと

お世話になります。
現在、C#を勉強し始めたところ、コンパイラの動作と参考にしている教科書で食い違いがあった為、質問させていただきます。

【前提】C#における継承の学習中
教科書:
スーパークラスのオーバーライド元となるメソッドに「virtual」、
サブクラスのオーバーライド先となるメソッドに「override」を記述しなくとも、
コンパイル時にエラーが出るが、コンパイルはでき、実行もできる。

コンパイル時:
*実際の警告文は下記参照願います。*
警告文が発生し、EXEファイルが生成されない。

【実現したいこと】
以下のことを知りたいです。
初歩的なことで申し訳ありませんが、ご教授願います。

1.教科書の「警告は出るが、コンパイルできる」は正しいのか。
2.(1が正しいとして)どのようにすれば、コンパイルは通るのか。

発生している問題・エラーメッセージ

inheritance.cs(53,35): warning CS0108: 'EnchancedMyObject.PrintData()' hides inherited member 'MyObject.PrintData()'. Use the new
 keyword if hiding was intended.

該当のソースコード

 using System;

 namespace foo
 {
     class Program
     {
         public static void Main(string[] args)
         {
            EnchancedMyObject obj = new EnchancedMyObject();
            obj.name = "テスト";
            obj.age = 20;
            obj.mail = "sample@sample.com";
            obj.PrintData();
            obj.PrintDataEnchanced();
            Console.ReadKey();
         }
     }

     class MyObject
     {
         public string name = "(noname)";
         public int age = 0;

         // オーバーライド元
         public void PrintData()
         {
             Console.WriteLine("名前:{0}, 年齢:{1}歳", name, age);
         }
     }

     class EnchancedMyObject : MyObject
     {
         public string mail = "(no mail)";

         // オーバーライド先
         public void PrintData()
         {
             Console.WriteLine("Method\"PrintData\" was overrided.");
         }

         public void PrintDataEnchanced()
         {
             Console.WriteLine("名前:{0}" + Environment.NewLine + "年齢:{1}" + Environment.NewLine + "メール:{2}.", name, age, mail);
         }
     }
 }

試したこと

オーバーライドするメソッドにvirtual, overrideを記述している場合は問題なくコンパイルでき、実行してオーバーライドされていることを確認しています。

補足情報(言語/FW/ツール等のバージョンなど)

現在、新しいものを試す意味も含め、OSXにVisual Studioをインストールし、
Visual Studio Codeにて、CSCを使用してコンパイルしています。
(実行時はMonoを使用)

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

warning と書いてあるものは警告です。通常、警告が出ても実行ファイルは作られます。作られないとするなら、正しいコードで実行ファイルが作られるかどうか、またオプションが正しいかどうかを確かめてください。
警告を出さないようにするには、警告文の中で書かれている通り、new キーワードを使ってください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/22 22:36

    回答ありがとうございます。
    オプションは盲点でした。しっかり確認してみます。
    一応、現状ではvirtualとoverrideを記述することでコンパイルが通ることを確認しています。

    キャンセル

check解決した方法

0

自己解決しました。
どうやら、教科書と自分の実行環境に違いがあった為、混乱したようです。

教科書:Visual Studio(バージョン不明)
自分:テキストエディタ(Visual Studio Code)

今回、問題となった部分は

// オーバーライド元
public void PrintData()
{
  Console.WriteLine("名前:{0}, 年齢:{1}歳", name, age);
}

// オーバーライド先
public void PrintData()
{
  Console.WriteLine("Method\"PrintData\" was overrided.");
}


上記のコードで、

教科書:警告文は出るが、コンパイルが通り、実行できる。
自分:警告文が出て、コンパイルが通らない。

という部分でした。

どうやら、Visual Studioでは
上記のようなソースコード(virtual - override、newのどちらも無い)場合、
暗黙的にnewを追加し、コンパイル・実行しているようです。
(Visual Studio 2017で上記ソースコードを実行し、生成されたEXEファイルをデコンパイルしたら判明しました)
この機能の有無により、教科書と自分の実行結果が異なる結果となったようです。

また、CSCを使ったコンパイル時はご指摘があった通り、
/nowarnオプションを付与することで警告を無視したコンパイルができそうです。
(※申し訳ありませんが、時間の都合上、まだ未検証です)

結論

結果の食い違いは実行環境の違いによるものでした。
Visual Studioでは設定にもよると思われますが、上記のソースコードは問題なく動作します。
IDEを使わず、自力でコンパイル・実行をする場合には、警告を無視するオプションが必要となるかと(未検証)。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/23 08:52

    nowarn は警告があってもコンパイルするオプションではなく、警告を出さないようにするオプションです。また CSC は警告があってもコンパイルします。そこではなく、VSCode の拡張機能のオプションを確認してください。

    キャンセル

0

1.教科書の「警告は出るが、コンパイルできる」は正しいのか。 
2.(1が正しいとして)どのようにすれば、コンパイルは通るのか。

1.が正しくて、コンパイルできてるのですよね?そこは確認できているのでは?
コンパイルが通る=正しく動作する、ではないことは理解できていますよね?

コンパイルできたからと言って、それがプログラマの意図した挙動でないと予想されるので、コンパイラはわざわざ警告を出しているのでしょう。

親クラスと子クラスで「同じ名前のメソッド」が定義されていた場合、コンパイラはコードを書いた人が

  • ポリモーフィックな挙動を期待している
  • まったく無関係な別のメソッドとして親の挙動を隠蔽したい

のいずれかが判断できないので、前者の場合は virtual - override と付けてほしいし、後者の場合は new キーワードによってその意図を明確にして欲しいということです。自分が意図した内容に従いコードを書けばよいだけです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/22 22:33

    回答ありがとうございます。

    >>1.が正しくて、コンパイルできてるのですよね?そこは確認できているのでは?
    >>コンパイルが通る=正しく動作する、ではないことは理解できていますよね?

    自分の中では「コンパイル=ソースコードがマシン語に翻訳され、実行用ファイル(今回ならEXEファイル)が生成される」という認識になっています。
    コンパイルがこの認識で合っているならば、現状はEXEファイルが出力されていないので、コンパイルは通っていないのかな、と思っています。
    勉強用に作ったファイルなので、オプション関係も含め、もうちょっと弄り回してみます。

    キャンセル

  • 2017/05/22 22:55

    > 現状はEXEファイルが出力されていないので、コンパイルは通っていないのかな、と思っています。

    質問文には「警告」しか記載されていないので、エラーを見逃しているのでなければ、プロジェクトの設定で「警告をエラーとして扱う」のオプションが設定されている可能性があります。

    キャンセル

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

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る