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

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

新規登録して質問してみよう
ただいま回答率
85.47%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

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

Q&A

解決済

3回答

632閲覧

派生クラス 仮想関数 重複include

JJJJJJJJJamm

総合スコア10

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

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

0グッド

0クリップ

投稿2020/04/09 15:11

編集2020/04/09 15:13

前提・実現したいこと

このプログラムで、#pragma onceを付けなかった場合に複数回重複includeされてしまうのは何故でしょうか。

Compilation error

In file included from main.cpp:2:0: shape.h:4:7: error: redefinition of 'class Shape' class Shape{ ^~~~~ In file included from main.cpp:1:0: shape.h:4:7: note: previous definition of 'class Shape' class Shape{ ^~~~~ In file included from main.cpp:2:0: shape.h:11:7: error: redefinition of 'class Rectangle' class Rectangle : public Shape{ ^~~~~~~~~ In file included from main.cpp:1:0: shape.h:11:7: note: previous definition of 'class Rectangle' class Rectangle : public Shape{ ^~~~~~~~~ In file included from main.cpp:2:0: shape.h:18:7: error: redefinition of 'class Circle' class Circle : public Shape{ ^~~~~~ In file included from main.cpp:1:0: shape.h:18:7: note: previous definition of 'class Circle' class Circle : public Shape{ ^~~~~~ In file included from main.cpp:2:0: shape.h:25:7: error: redefinition of 'float Rectangle::getArea()' float Rectangle::getArea(){ ^~~~~~~~~ In file included from main.cpp:1:0: shape.h:25:7: note: 'virtual float Rectangle::getArea()' previously defined here float Rectangle::getArea(){ ^~~~~~~~~ In file included from main.cpp:2:0: shape.h:28:7: error: redefinition of 'float Rectangle::getPerim()' float Rectangle::getPerim(){ ^~~~~~~~~ In file included from main.cpp:1:0: shape.h:28:7: note: 'virtual float Rectangle::getPerim()' previously defined here float Rectangle::getPerim(){ ^~~~~~~~~ In file included from main.cpp:2:0: shape.h:31:7: error: redefinition of 'float Circle::getArea()' float Circle::getArea(){ ^~~~~~ In file included from main.cpp:1:0: shape.h:31:7: note: 'virtual float Circle::getArea()' previously defined here float Circle::getArea(){ ^~~~~~ In file included from main.cpp:2:0: shape.h:34:7: error: redefinition of 'float Circle::getPerim()' float Circle::getPerim(){ ^~~~~~ In file included from main.cpp:1:0: shape.h:34:7: note: 'virtual float Circle::getPerim()' previously defined here float Circle::getPerim(){ ^~~~~~ make: *** [main.o] Error 1

該当のソースコード(shape.h)

C++

1#pragma once 2#include<iostream> 3#include<cmath> 4using namespace std; 5class Shape{ //virtual base class 6 public: 7 virtual float getArea() = 0; //pure virtual function 8 virtual float getPerim() = 0; //pure virtual function 9 protected: 10 float w, h, r; 11}; 12class Rectangle : virtual public Shape{ //derived class 13 public: 14 Rectangle(){} 15 Rectangle(const float& width,const float& height){w = width; h = height;} 16 float getArea(); 17 float getPerim(); 18}; 19class Circle : virtual public Shape{ //derived class 20 public: 21 Circle(){} 22 Circle(const float& radius){r = radius;} 23 float getArea(); 24 float getPerim(); 25}; 26float Rectangle::getArea(){ //override 27 return w * h; 28} 29float Rectangle::getPerim(){ //override 30 return (w + h) * 2; 31} 32float Circle::getArea(){ //override 33 return r * r * acos(-1); 34} 35float Circle::getPerim(){ //override 36 return 2 * r * acos(-1); 37}

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

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

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

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

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

guest

回答3

0

ベストアンサー

こんにちは。

このプログラムで、#pragma onceを付けなかった場合に複数回重複includeされてしまうのは何故でしょうか。

エラーメッセージを見る限り、main.cppの1行目と2行目で#include "shape.h"しているようです。
流石に2連続で同じヘッダをインクルードしたいケースはないと思いますが、例えば、campus.hとbrush.hがshape.hをインクルードしており、campus.hとbrush.hをmain.cppからインクルードしたいようなケースがありますが、何も対策しないと同様の重複定義エラーがでます。

そのような重複定義を回避するための機能が、#pragma onceです。

投稿2020/04/09 17:25

Chironian

総合スコア23272

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

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

0

#pragma onceはあんま関係なくて、メンバー関数の定義のときにinline指定しましょうというお話ですね。まあメンバー関数に限らずすべての関数定義をヘッダーに書くときはinline指定するべきですが。ただしtemplate関数は暗黙でinline指定されるほか、class定義の中でメンバー関数の宣言と定義を同時に行う場合も同様です。

cpp

1inline float Rectangle::getArea(){ //override 2 return w * h; 3}

inline指定とはたまに誤解があるので念の為書くと、「関数を強制的にインライン展開させるための機能」ではありません。
詳しくは
cpp17book/035-cpp17-core-inline-variables.md at master · EzoeRyou/cpp17book

投稿2020/04/09 15:32

yumetodo

総合スコア5850

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

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

JJJJJJJJJamm

2020/04/09 16:03

回答ありがとうございます。試しに#pragma onceを消して関数定義の際にinline指定してみましたが、同じ内容のエラーが出てしまいました。まだ私のコードに他に直すべきところがあれば、教えていただきたいです。よろしくお願いします。
yumetodo

2020/04/10 03:08

いや、#pragma onceないし手動でのinclude guardがいらないって話じゃないです。それだけじゃ不十分だよって言いたかった。
yumetodo

2020/04/10 03:09

結局#includeというのは単なる自動コピペマシーンに過ぎないので、それ以上の何も行わないのです。 早くC++にmoduleが来てほしい・・・
JJJJJJJJJamm

2020/04/11 08:04

すみません、こちらの理解不足でした。。。回答ありがとうございます、リンクの方もとても勉強になりました。
guest

0

いかにも標準ライブラリにあるようなクラス名ですが、そこらへんは大丈夫なんでしょうか

投稿2020/04/09 15:15

y_waiwai

総合スコア87784

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問