(C++) static constの使い方

今日も勉強になったので備忘録を残すことにしよう。

今日はC++のstatic constについて。

Javaのstatic finalとほとんど同じだろう?というつもりで書いたつもりが、なぜかVisual Studioに怒られる。

1>ConstTest.obj : error LNK2001: 外部シンボル “”public: static int const common::CommonValues::YEAR” (?YEAR@CommonValues@common@@2HB)” は未解決です。

こんな感じで。

意味不明だったけど大学院の先輩から後輩まで多くの方がTwitter上で助けてくれました。

とりあえず自分の書いたコードは以下の3つ

CommonValues.h

[cpp]
#pragma once

namespace common{

 class CommonValues
 {
 public:
 CommonValues(void);
 ~CommonValues(void);
 static const int YEAR;
 };

}
[/cpp]

CommonValues.cpp

[cpp]
#include "stdafx.h";
#include "CommonValues.h"

namespace common{

 const int YEAR = 365;

 CommonValues::CommonValues(void)
 {
 }


 CommonValues::~CommonValues(void)
 {
 }

}
[/cpp]

Main.cpp

[cpp]
#include "stdafx.h";
#include "CommonValues.h"
#include <iostream>

using namespace std;
using namespace common;

int main(){
 CommonValues c;
 cout << "start\n";
 cout << CommonValues::YEAR << endl;
}

[/cpp]

これをコンパイルすると上記のエラー。

答えはCommonValues.cppのconst int YEAR = 365;

これnamespace commonのグローバル変数になってんじゃねーか!(そう言うのかは知らんが)

正しくはconst int CommonValues::YEAR = 365;

またはそもそもそこに書かずにCommonValues.hの宣言部分を

static const int YEAR = 365;とする。

.hにまとめて書いた方がインライン展開されるのでコンパイラの最適化が効きやすいとかなんとか。ふむ、納得。

とにかくつまらないミスをしていただけだった・・。

Javaだと.hなんかに宣言分けずに一緒に書くから、今回のケースはすっかりハマってしまいました。今後は気を付けよう。

しかし今回のコンパイルエラーはなぜに未解決シンボルって出たんだろう。

Mainから見てYEARは名前解決できると思うんだけど。

でも、それはconstなのに値の定義が無くて・・・。だから.hで宣言されたconst変数の先が未解決ってことか・・・?

うーん・・・コンパイラは難しい。

とにかく今後もスキルを磨いていこう。

テンション

今日は大学に卒業した先輩が来た。

相変わらずだった。

一緒にご飯食べて少し話しただけだけど楽しかった。

会社の話とか聞いて少し焦りを覚える・・・。

うん、やっぱ就職まで、いやしてからも気は抜けないな・・・。

情報系、しかも院卒なのに同期じゃ底辺とか、院卒なのに高専卒2年目の先輩社員にアゴで使われるとか絶対嫌だし・・・。

理由はほかにもいろいろあるけど、とにかく勉強と仕事両方できる人間にならねば。

明日からまた頑張ろう。

Cは参照渡しじゃねーし

今日も備忘録を残そう。

今日は値渡し(call by value)と参照渡し(call by reference)の話。

いつかは覚えてないけどここ3年程の間にC言語に参照渡しは無くて、全て値渡しだということを覚えた。

色々な入門サイトが参照渡しと言っているけれど全ては間違いだったんだっ!

自分の大好きなwisdom softもJAVAは参照渡しと言っている・・・軽く鬱。

嘆かわしいことに俺のバイブル、独習Cも参照渡しと言っている・・・。けど、著者が悩んだ末にあえて参照渡しと書いたような痕跡があった。

以下、引用。

特に指示しなければ、Cは値渡しで引数を渡します。つまり、関数を呼び出すために使われた引数に関数の内部から変更を加えることはできません。関数内部の仮引数に何が起こっても、外部の引数には影響しないのです。しかし、第6章で説明したように引数へのポインタを渡せば、参照渡しを実現できます。
出展:独習C, 著:Herbert Schildt, 訳:柏原 正三

指示すれば参照渡しができるとは言っていない!

あくまで実現できると言ってる・・・!

まあ、とにかくCとかJavaは参照渡しはできねーんだ・・・。

詳しい話はja.wikipediaとかこの議論にあった。

議論はなかなか読む価値があったと思う。

特に

何が引数に渡されるか? 値か? 参照か?という話ではなく、実引数をどのように仮引数に渡すか?

というくだりが凄く為になった。

そうそう、はじめてC言語はすべて値渡しと覚えたときには”所詮アドレスも値だから”って覚えてました。

なるほど・・・そうじゃないんだ!

もっとまとめようかと思ったけど、wikiと議論見ればわかるだろうし、先人が何人も似たような記事書いてるのでやめる。

wikipediaだと具体例が無くて分からなかったけど、このC#の例のおかげで理解できた。

http://ufcpp.net/study/csharp/sp_ref.html

なるほど、refをcallee,callerどっちにもつけている。

あれ・・・しかしwikiにはCのように明示的にアドレス演算子を使うものは参照渡しとは呼ばない。とあるんだけど・・・

refとか凄く明示的です・・・。

いや多分アドレス演算子じゃないからいいんだろうけどね。

まあ、とにかく本当の参照渡しが理解できてきた。

うんうん、今日も有意義な1日であった。