ページ 1 / 1
【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 01:14
by takahashi
ソースファイルを作らずにクラスの静的メンバ変数の実態を生成したいです。小さなものであればわざわざソースファイルは作りたくないという理由です。
次のようなdefクラスを作ってwindowサイズを静的メンバ変数として用意しました。
Def.h
コード:
#pragma once
class Def
{
public:
static const int windowWidth;
static const int windowHeight;
};
const int Def::windowWidth = 480;
const int Def::windowHeight = 360;
いろいろと調べたらこのファイルを2回以上インクルードしたら多重定義になってしまうらしくエラーが起きてしまうらしいのです。
ですが、現状普通に動作しています。
C++のバージョンの変化なのか、この書き方は普通に大丈夫なんなのかわかりません。
環境
OS : WIndows
コンパイラ:わからないのですがvisualstudio2019を使ってます。
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 10:22
by Meta3
#pragma once
が記述してあるから大丈夫ですよ。
コード:
#include <iostream>
#include "c1.hpp"
#include "c1.hpp"
using namespace std;
int main()
{
cout << Def::windowWidth << endl;
}
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 10:26
by Meta3
visualstudio2019を使ってます。
コード:
c:\b>cpp
c:\b>cl /EHsc c1.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.26.28806 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
c1.cpp
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:c1.exe
c1.obj
c:\b>c1.exe
480
c:\b>
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 10:47
by Meta3
>ソースファイルを作らずにクラスの静的メンバ変数の実態を生成したいです。小さなものであればわざわざソースファイルは作りたくないという理由です。
static(クラスの静的メンバ変数)は実態(実体 インスタンスのことね)を生成しなくても使えますよ。
でも さすがにソースファイルを作ら無ければ動かないですよ。
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 17:20
by takahashi
回答ありがとうございます!
progma onceがあるから多重定義にならないんですね!これがほしい回答でした。
質問の仕方が悪くて、意図が伝えられてませんでした。
さきほど用意したクラスのDef.hがあると思うのですが、普通ならDef.hとDef.cppに分けるのが一般的だと調べてたらでてきました。次の通りです。
Def.h
コード:
#pragma once
class Def
{
public:
static const int windowWidth;
static const int windowHeight;
};
Def.cpp
コード:
#include "Def.h"
const int Def::windowWidth = 480;
const int Def::windowHeight = 360;
このくらい小さかったらわざわざファイル分けたくないなーと思い一つにまとめたのが最初の質問の次のクラスです。
コード:
#pragma once
class Def
{
public:
static const int windowWidth;
static const int windowHeight;
};
const int Def::windowWidth = 480;
const int Def::windowHeight = 360;
このDef.hをmain.cppで呼び出して使おうとしてました。
しかし、質問でも言った通り次の箇所がヘッダーに書くと多重定義になってしまうと思ってたのですが普通に動作してたので不安になり質問しました。
const int Def::windowWidth = 480;
const int Def::windowHeight = 360;
ただ#pragma onceがあることでそれが防げるとわかったので解決しました。
ありがとうございます!
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 18:21
by usao
> 多重定義になってしまう
という話は,インクルードガード(#pragma once)に関連する話ではなく,
「そのヘッダを A.cpp と B.cpp がincludeした場合に多重定義になる」という側の話であるように思うが.
試しに,そのクラスDef に static const メンバとして int ではない std::string 型とか適当な物を持たせて,
その実態を Def.h に定義した状態で,
Def.hを複数のcppからincludeしてみればわかる.
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 18:25
by Meta3
あ 失礼
Def.hーーーc1.hpp
main.cppーc1.hpp
として作りました
VisualStudio2019コマンドラインで実行ーーーcl /EHsc c1.cppーーー
c++はヘッダーは .hppを使うのが一般的
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 18:25
by Meta3
あ 失礼
Def.hーーーc1.hpp
main.cppーc1.hpp
として作りました
VisualStudio2019コマンドラインで実行ーーーcl /EHsc c1.cppーーー
c++はヘッダーは .hppを使うのが一般的
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 18:27
by usao
static const int の場合にエラーにならないのは,それがガチの定数だからだと思う.
言わば特殊ケースであって,
「#pragma once とさえ書けば static なメンバの定義をヘッダファイルに書いて良い」という話ではない.
「さっきstringがどうの」と書いたが,もっと簡単に,constをハズしてみれば,エラーになることを確認できるハズ.
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 18:28
by Meta3
Def.hーーーc1.hpp
main.cppーc1.cpp
の間違い
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 18:47
by usao
> c++はヘッダーは .hppを使うのが一般的
・Boostとかだと ".hpp" が使われる
・Visual Studioでファイル新規追加する際の拡張子はC++でも".h"である.
・".hh" なんてのを使う文化もあるみたいだし.
・なんなら,STLは拡張子無いし.
「一般的」と言うほどの話とも思えないけど.
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月03日(木) 18:53
by takahashi
今までソースファイルがmain.cppの一つのみでプログラムを書いていたので動作していたんですね。
複数のソースファイル用意して、先ほどのクラスをincludeしたらエラーがでちゃんとでました。
やはりソースファイルとヘッダーファイルでわけるべきですね。
またヘッダーファイルというものが.h以外にもあるということが勉強になりました。
ありがとうございます。
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月05日(土) 01:01
by Meta3
c1.hpp
コード:
#pragma once
class Def
{
public:
static const int windowWidth=480;
static const int windowHeight=360;
};
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月05日(土) 01:05
by Meta3
c1.cpp
コード:
#include <iostream>
#include "c1.hpp"
#include "c1.hpp"
using namespace std;
extern int disp();
int main()
{
cout << Def::windowWidth << endl;
disp();
return 0;
}
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月05日(土) 01:09
by Meta3
c2.cpp
コード:
#include <iostream>
#include "c1.hpp"
using namespace std;
int disp()
{
cout << Def::windowHeight << endl;
return 0;
}
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月05日(土) 01:25
by Meta3
エラーなんか出ないじゃないか
自作のヘッダーはcとかぶるときがあるから.hppにするといい VisualStudio2019使用
コード:
c:\b\p>cl /EHsc c1.cpp c2.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.26.28806 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
c1.cpp
c2.cpp
コードを生成中...
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:c1.exe
c1.obj
c2.obj
c:\b\p>c1.exe
480
360
c:\b\p>
[code]c:\b\p>cl /EHsc c1.cpp c2.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.26.28806 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
c1.cpp
c2.cpp
コードを生成中...
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:c1.exe
c1.obj
c2.obj
c:\b\p>c1.exe
480
360
c:\b\p>
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月05日(土) 09:09
by Meta3
C++ は C#のように開発責任者アンダース・ヘルスバーグ
https://ja.wikipedia.org/wiki/%E3%82%A2 ... C%E3%82%B0 がいるわけではなく たくさんの処理系・実装がある
だから マイクロソフトのVisualStudio2019を使ってC17準拠での話 とか言わないと正確に言えない言語です
わたしはC#を先に使ったので分かりやすかった
C#の#はC++++の意味で(#は分解すると++++)C++はC#を追っかけている
C++を学ぶならC#を先に学ぶことをお勧めします
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月05日(土) 09:44
by Meta3
VisualStudio2019では
cl c1.c とすればC言語
cl /EHsc c1.cpp とすればC++言語
としてビルドしてくれる
ところが
cl /P c1.c とするとC++言語
としてビルドしてくれる
逆に
cl /C c1.cpp とすればC言語
としてビルドしてくれる
これは便利である
C言語と「C++言語としてのC言語」が微妙にが違うからである
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月05日(土) 12:49
by Meta3
/P-----/TP
/C-----/TC
の間違い
VisualStudioではC++の開発が行えます。しかし、C++とC言語は微妙にちがいます。
たとえば、型変換や、intの省略などで違いが出てきます。C++はC言語よりも安全性と正確性を高めるための工夫がされています。
なのでC言語用に作られたプログラムをコンパイルしようとすると、その違いのせいでコンパイルエラーになることがしばしばあります。
では純粋なC言語としてコンパイルすることは出来ないのか?いえ、実は簡単に出来ます。
意外と知らない人がいるようなので
VisualStudio2019
cl ヘルプ
/Tc<source file> ファイルを .c としてコンパイルする
/Tp<source file> ファイルを .cpp としてコンパイルする
/TC すべてのファイルを .c としてコンパイルする
/TP すべてのファイルを .cpp としてコンパイルする
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月05日(土) 18:00
by 参照魚
static inline と宣言すればいけると思います。
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月06日(日) 19:40
by Meta3
最初にみたときこんな冗談のようなソースで動かないだろうと思ったが動くのことでヘッダーを忠実に最初のものにしてビルドしてアセンブリーにおとしてみました
c1.hpp
コード:
#pragma once
class Def
{
public:
static const int windowWidth;
static const int windowHeight;
};
const int Def::windowWidth = 480;
const int Def::windowHeight = 360;
c1.hpp
コード:
#include <iostream>
#include "c1.hpp"
#include "c1.hpp"
using namespace std;
extern int disp();
int main()
{
return 0;
}
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月06日(日) 19:46
by Meta3
コード:
c:\b\p>cpp
c:\b\p>del c1.exe
c:\b\p>cl /EHsc c1.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.26.28806 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
c1.cpp
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:c1.exe
c1.obj
c:\b\p>c1.exe
c:\b\p>cl /Fa c1.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.26.28806 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
c1.cpp
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:c1.exe
c1.obj
c:\b\p>
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月06日(日) 19:50
by Meta3
コード:
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.26.28806.0
TITLE c:\b\p\c1.cpp
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC ?windowWidth@Def@@2HB ; Def::windowWidth
PUBLIC ?windowHeight@Def@@2HB ; Def::windowHeight
CONST SEGMENT
?windowWidth@Def@@2HB DD 01e0H ; Def::windowWidth
?windowHeight@Def@@2HB DD 0168H ; Def::windowHeight
CONST ENDS
PUBLIC _main
; Function compile flags: /Odtp
_TEXT SEGMENT
_main PROC
; File c:\b\p\c1.cpp
; Line 9
push ebp
mov ebp, esp
; Line 10
xor eax, eax
; Line 11
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月06日(日) 19:54
by Meta3
CONST SEGMENT
に値がかきこまれてますね
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月06日(日) 20:24
by Meta3
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月06日(日) 20:50
by Meta3
>static inline と宣言すればいけると思います。
そうですね。
https://cpprefjp.github.io/lang/cpp17/i ... ables.html
[外部リンケージを持つ変数に対しインラインinlineを指定することで、複数の翻訳単位で同じ変数を宣言できるようになり、変数の実体はただ一つとすることができる。
C++14までは関数のみインライン指定ができたが、C++17では関数、変数ともにインライン指定が可能になった。
これによりヘッダのみで変数の定義を行うことができるようになり、従来のようにヘッダで変数を宣言しソースで変数の実体を定義する必要がなくなった。]
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月06日(日) 22:04
by 参照魚
実行中に値が変更されないのであれば、constexprで宣言する方があっているかと思います。
static constexpr int windowWidth = 480;
static constexpr int windowHeight = 360;
Re: 【C++】ソースファイルを作らずに静的メンバ変数の実態の生成
Posted: 2020年12月06日(日) 22:56
by Meta3
「なるほど ROM に置ける値か」
これまでconst修飾してきたものには2種類あった、ひとつはROM化可能な値、もうひとつは実行時にしか決まらないがいったん初期化したあとは二度と変更されない値である。C++11以降、前者はconstexprが受け持ち、後者はconstが受け持つことになった。
constexpr指定子は、constexprの制約を満たした変数の定義、関数と関数テンプレートの宣言、staticデータメンバーの宣言に対して使用できる。
2つの区別
constは型修飾子である。const intはint型であるが、初期化したあとは二度と変更されない変数である。C++11以降、constexprが導入されたあとは、constはRAMにしか配置できない変数に対して使う修飾子となった。
constexprは型修飾子ではなく、型指定子である。型を修飾するものでなく、ROM化できる、または、ROM化できる可能性がある、という意味を持つ指定子である。
https://qiita.com/saltheads/items/dd65935878a0901fe9e7