C++ ファイル分割と重複定義

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
stm

C++ ファイル分割と重複定義

#1

投稿記事 by stm » 9年前

環境 visual studio2013 windows8.1
C++ 入門サイトやここのサイトを一通り勉強しました


一つのファイルに同じクラス定義や関数定義を二つ書くと
コンパイルの段階でエラーになります
では次の二つの場合の挙動の違いについて教えてください

test.h------------------------

コード:

void Test(){

printf("test");
}
---------------------------
a.cpp-------------------------

コード:

#include "testh.h"
#include<stdio.h>

void Test1();

int main(){

Test1();

}
------------------------------
b.cpp--------------------------------

コード:

#include"testh.h"

void Test1(){

Test();
printf("test1");
}
------------------------------

↑はコンパイルは通りますがリンカの段階でTest()が二重定義とされエラーになります


test.h-----------------------------

コード:

class CTest{
public:
int a;
int b;

};
---------------------------
a.cpp-------------------------

コード:

#include "testh.h"
#include<stdio.h>

void Test1(CTest& Test);

int main(){
CTest Test;
Test1(Test);
return 0;
}
------------------------------
b.cpp--------------------------------

コード:

#include"testh.h"

void Test1(CTest& Test){

Test.a = 5;
Test.b = 3;
}
------------------------------
↑問題なくコンパイルもリンクも通る


①はTest()の定義がa.objとb.objにそれぞれインクルードされたため同じ関数の定義がファイルをまたいで二つあるのでリンカエラーが起きたのだと思います
ならば②も同様にファイルをまたいでCTestのクラス定義がa.objとb.objにインクルードされているのでエラーが起きると思うのですが、起きません。

今ままでなんとなくファイル分割をしてきたので、この違いがわかりません。
どうかご教授ください

なるべく専門的な範囲(リンカの挙動の違いとか)でわかりやすく(無茶ですいません)おねがいします

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: C++ ファイル分割と重複定義

#2

投稿記事 by h2so5 » 9年前

クラス定義は重複していてもエラーにはなりません。

naohiro19
記事: 256
登録日時: 13年前
住所: 愛知県

Re: C++ ファイル分割と重複定義

#3

投稿記事 by naohiro19 » 9年前

struct でも同じことが言えます。

stm

Re: C++ ファイル分割と重複定義

#4

投稿記事 by stm » 9年前

同じクラス定義を同じソースファイルに二つ書くとコンパイルエラーになりますが
同じクラス定義をファイルを跨いで二つ書いてもエラーになりません

この違いをコンパイラやリンカの挙動の観点から教えてください

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C++ ファイル分割と重複定義

#5

投稿記事 by softya(ソフト屋) » 9年前

用語の細かい所はおいておいて、コンパイラは1つのソースファイルとインクルードしているヘッダだけをみてオブジェクトファイルを生成します。なので1つのソースファイル内で検出できるエラーを検出します。
リンカはオブジェクトファイルを結合しますので、名前がオブジェクトファイル間で同じものが出てくる場合リンカでしかエラー判定しようがりません。
コンパイラとリンカの動作を考えれば推測できると思いますが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stm

Re: C++ ファイル分割と重複定義

#6

投稿記事 by stm » 9年前

コード:

// Test1.cpp
class CTest
{
public:
    int a;
    int b;

    void Func();
};

void CTest::Func()
{
    b = 0;
}

CTest a;

コード:

// Test2.cpp
class CTest
{
public:
    int a;

    void Func();
};

CTest b;

int main()
{
    b.Func();
}
これをコンパイルリンクしてもエラーは出ないそうです((((;゚Д゚)))))))
関数で、同じ名前違う実装の関数を二つ定義したらエラーになるのに、クラス場合は許されちゃうんですね〜
クラス定義と関数定義の違いを勉強してきます

ISLe()

Re: C++ ファイル分割と重複定義

#7

投稿記事 by ISLe() » 9年前

【定義】には2種類あります。
1. 宣言のうち、実体の生成を伴うもの
2. 宣言以外で識別子を生成するもの

関数定義は1.で、クラス定義は2.です。

1.の定義が現れればコンパイル単位で実体が生成されます。

2.の定義は、コンパイル単位で、必要なときに既に定義されていなければコンパイルエラーになりますが、定義自体は実体を持ちません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: C++ ファイル分割と重複定義

#8

投稿記事 by softya(ソフト屋) » 9年前

話が飛びましたがコンパイルとリンクの違いは理解されたのでしょうか?

>これをコンパイルリンクしてもエラーは出ないそうです((((;゚Д゚)))))))
>関数で、同じ名前違う実装の関数を二つ定義したらエラーになるのに、クラス場合は許されちゃうんですね〜
>クラス定義と関数定義の違いを勉強してきます

関数のオーバーロードを調べて下さい。
調べると分かりますがC++の場合はクラスではない関数でもオーバーロード出来ます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stm

Re: C++ ファイル分割と重複定義

#9

投稿記事 by stm » 9年前

おおお!ISLe()さんの情報が多分僕が一番知りたかったことです。クラス定義と関数定義の違いが明確になりました。「識別子」「関数の実体」の具体的専門的な説明が欲しいのですが、参考になるサイト文献があれば教えてください。

ソフト屋さん
関数のオーバロードは引数の種類個数=シグネチャが違わなければ作用せず、おなじ関数名、シグネチャの関数定義がファイルを跨いで存在すると、ファイル単位で行われるobjファイル生成コンパイルは正常に行われるが、それらをつなげる(コンパイル時に未設定だった、他ファイルにある関数へのアドレスを設定する?)リンカの段階で、同じ関数名を区別できないので、リンクエラーになる

私の理解はこんな感じです

ここで私は、「区別できない関数定義をファイル跨ぎで二つ書くとダメだよなー。え?でもクラス定義は分割したファイルそれぞれにインクルードしてきたじゃん。なんで関数の時のようにエラーでないの?」と思ったわけです。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: C++ ファイル分割と重複定義

#10

投稿記事 by h2so5 » 9年前

stm さんが書きました:おおお!ISLe()さんの情報が多分僕が一番知りたかったことです。クラス定義と関数定義の違いが明確になりました。「識別子」「関数の実体」の具体的専門的な説明が欲しいのですが、参考になるサイト文献があれば教えてください。
C++の規格書を読みましょう。
識別子については"3.5 Program and linkage" , 関数の実体については、"3.1 Declarations and definitions" に書かれています。
http://www.open-std.org/jtc1/sc22/wg21/ ... /n3690.pdf

stm

Re: C++ ファイル分割と重複定義

#11

投稿記事 by stm » 9年前

ありがとうございます!!(ひえー英語だー)
最後に質問なんですが、プログラマとして働くならば、触ったことのない言語はこのように外国語の規格書をよむのが常識なのでしょうか、それとも普通は分かりやすい入門書やサイトを利用して勉強し、深く知る必要があるときに規格書を漁るものなのでしょうか?

ISLe()

Re: C++ ファイル分割と重複定義

#12

投稿記事 by ISLe() » 9年前

JISC 日本工業標準調査会のJIS検索で日本語の規格書を読めます。
C言語はJISX3010、C++言語はJISX3014です。

日本語の訳は間違っていることがけっこうあるので注意してください。
ネットで検索すればJISの何が間違っているという情報も見付けることができますが。

stm

Re: C++ ファイル分割と重複定義

#13

投稿記事 by stm » 9年前

答えてくださったみなさん、ありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る