学校の授業では構文は教えてくれるがその機能が何のためにあるかを教えてくれない。なぜだ。なぜなのだ。
そんなわけで、ここでは「クラスとは何で、使うと何がいいのか」について私なりの解釈を載せようと思う。
まず、かなり極端な例だが、以下のようなプログラムを考える。
//身長を入力する関数 double scanHeight(){ double h; printf("身長を入力してください:"); scanf("%lf",&h); return h; } //体重を入力する関数 double scanWeight(){ double w; printf("体重を入力してください:"); scanf("%lf",&w); return w; } //BMIを計算する int main(){ double HeightA = scanHeight(); double WeightA = scanWeight(); double HeightB = scanHeight(); double WeightB = scanWeight(); double BMI_A = WeightA*HeightA*HeightA; double BMI_B = WeightB*HeightB*HeightB; }
このプログラムは正常に動作する(多分)。だが、コーディングという観点からみるとバグを生みやすい書き方をしているといえる。
以下のようなバグを作る可能性がある。
int main(){ double HeightA = scanHeight(); double WeightA = scanHeight();//コピペミスかなにか。コンパイルは通る double HeightB = scanHeight(); double WeightB = scanWeight(); double BMI_A = WeightA*HeightA*HeightA; double BMI_B = WeightB*HeightB*HeightB; }
このようなバグを作った場合、実行時には三回連続で身長を聞かれてしまう。
ここで問題である。なぜこのソースコードがコンパイルを通るのか?
WeightAという変数を体重用の変数と考えているのも、scanHeightという関数を身長用の関数だととらえているのも、いずれも人間が勝手にそうだと言い張っているだけなのだ。コンピュータ(コンパイラ及びCPU)には、このプログラムは以下のように見える。
int main(){
double型の変数1 = doubleを返す関数1();
double型の変数2 = doubleを返す関数1();
double型の変数3 = doubleを返す関数1
double型の変数4 = doubleを返す関数2;
double型の変数5 = 変数2*変数1*変数1;
double型の変数6 = 変数4*変数3*変数3
}
変数名WeightAや関数名scanHeightはあくまで人間がわかりやすいように人間が勝手につけたものだ。コンピュータにとってはWeightAもHeightAも、double型の二つの変数、程度の違いしかない。
ここでもし、以下のように書けたら、きっとエラーが出るに違いない。
//身長を入力する関数 heightValue_t scanHeight(){...} //体重を入力する関数 weightValue_t scanWeight(){...} int main(){ heightValue_t HeightA = scanHeight(); weightValue_t WeightA = scanHeight();//エラー WeightAは体重型だがscanHeightが返すのは身長の値 heightValue_t HeightB = scanHeight(); weightValue_t WeightB = scanWeight(); bmiValue_t BMI_A = WeightA*HeightA*HeightA; bmiValue_t BMI_B = WeightB*HeightB*HeightB; }
C++が扱えるデータの種類は文字コード(char)や小さな整数(short)や大きな整数(int)や小数(double)といった、「数値」だけである。
それだけでもプログラムを組むことはできるのだが、「体重」や「身長」や「人間」や「車」といった、現実に存在する様々な種類のデータを扱いたい。
データの種類を追加することで、現実世界に存在するモノに対する処理を、ソースコード上に、C++言語の文法で記述できるようにするための機能。
それがクラスなのである。
例えば、
class Apple{ unsigned char Color[4]; double weight; };
というプログラムを書いたら、それは
このプログラムには「リンゴ」という種類(データ型)が定義されており、リンゴというモノ(インスタンス)には、色と重さがある
という日本語を、C++語に翻訳したことになるのだ。
続く...
C++11のunique_ptr<>。これ基本的な考え方は大したことないんだが物凄く便利だ。
関数内でメモリを確保するときは、スタック領域に確保するかヒープ領域に確保するかの二通りの考え方がある。
スタック領域に確保する場合:
メリット:スコープを抜けたときに自動で解放してくれる
デメリット:あまり大きなメモリは確保できない , サイズが固定である
ヒープ領域に確保(new)する場合:
メリット:大きなメモリを確保できる , 実行時にサイズを指定できる
デメリット:明確なdeleteを忘れるとメモリリークを起こす
問題は、狭いスコープ内、例えば関数内、if文の{}内などでメモリを確保したくなり、サイズを実行時に指定したくしかも大きなサイズが必要というケースは頻繁にあるということだ。
少し余分に確保しておく、という方法が取れればそれでもいいが、そうでない限りnewを使うしかなくなる。すると同時にdeleteの義務が発生してしまうのである。
std::unique_ptrはこのような場合に用いることができる、
「スコープを抜けたら自動的に解放してくれるスタック変数のメリット」と
「大きな領域を動的に確保できるヒープのメリット」
を足したような素晴らしいポインタである。
#include <memory> #pragma warning(disable:4996) struct RGB { unsigned char r; unsigned char g; unsigned char b; }; int main() { int width; int height; scanf("%d %d", &width, &height); bool makeimage = true; //フラグが経っているときだけ画像を作成し、何かする if (makeimage == true) { std::unique_ptr<RGB[]> image = std::unique_ptr<RGB[]>(new RGB[width*height]); for (int i = 0; i < width*height; i++) { image[i].r = 0; image[i].g = 0; image[i].b = 0; } } return 0; }
このプログラムでは sizeof(char)×3×任意の値×任意の値 という、場合によっては巨大なメモリを動的に確保するが、delete [] の必要がない。書かなくても、ifブロックを抜けた時点で速やかに解放される。
GCではないので、コンピュータの気まぐれでいつ解放されるかわからない、という不安もついてこない。
----------------------
書きかけかも?
普通、光は水に入ると次第に減衰していく。だから極めて浅いところでは色がなく、浅いところでは明るい色になり、深いところでは暗い色になる。
ところがCyclesのGlassは光の減衰を再現してくれないらしい。だから薄く色を付けたGlassのオブジェクトを使うと沼みたいになる。
仕方がないのでVolumeを使用。表面には別に半透明なマテリアルを指定し、Voronoiで波を再現して貼り付けている。
C++のDLLの中に、関数ポインタを取る関数が外部に公開されている。
これをC#から使いたい。
どういうわけか、以下コードのCallFunctionに渡す関数ポインタの型をtypedefした関数ポインタ型(CallFP)にしたところランタイムエラーが起こる。
仕方がないので、void*で受け取って呼び出し直前にキャストするようにしたところうまくいった。今のところ、意味が分からない。
ちなみに、DLLDefs.hはDLL作成時に使用するヘッダで使っているもの。
dlltest.h
#include "DLLDefs.h" #include <cstdint> /////////////////////////////////// /// C++側 (ヘッダ) ///////////////// /////////////////////////////////// int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved); typedef void(WINAPI *CallFP)(std::int32_t a, std::int32_t b); __DLL_PORT void WINAPI CallFunction(void* p,std::int32_t in1,std::int32_t in2);
dlltest.cpp
#include <Windows.h> #include "dlltest.h" /////////////////////////////////// /// C++側 (cpp) ///////////////// /////////////////////////////////// int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: //初期処理 break; case DLL_PROCESS_DETACH: //終了処理 break; } return 1; // OK }; void WINAPI CallFunction(void* p, std::int32_t in1, std::int32_t in2) { CallFP cp = static_cast<CallFP>(p); (*cp)(in1, in2); }
using System; using System.Runtime.InteropServices;//Marshal用 /////////////////////////////////// /// C#側 (呼び出し)///////////////// /////////////////////////////////// namespace ConsoleApplication1 { //コールバック関数の型を宣言 [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate void TypeOfCallBack_t(System.Int32 a, System.Int32 b); class Program { //DLLの中の関数を宣言 [DllImport("Project1.dll",EntryPoint = "CallFunction") ] public static extern void CallFunction(IntPtr callbk,Int32 in1,Int32 in2); //コールバック関数本体。この関数がDLL経由で呼び出される static public void CallBackMain(Int32 a, Int32 b) { Console.Write(a + b + "\n"); } static TypeOfCallBack_t delgobj; static GCHandle gch; //エントリポイント public static void Main(string[] args) { delgobj = CallBackMain; IntPtr ptr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( delgobj ); gch = GCHandle.Alloc(delgobj); //関数を呼び出す CallFunction( ptr ,10,15); Console.Read(); gch.Free(); } } }
DLLを扱う際にimport,exportを分けるファイル。
DLLを作るプロジェクトへ読み込んだ場合は、プロジェクトの設定などでDLL_EXPORT_DOを定義しておけば、関数宣言時に__DLL_PORTを付けると公開関数となる
DLLを使うプロジェクトへ読み込んだ場合は、libをリンクするだけで関数を使えるようになる。
#ifdef DLL_EXPORT_DO /* DLLを作る場合 */ #define __DLL_PORT extern "C" __declspec(dllexport) #else /* DLLを使う場合 */ #define __DLL_PORT extern "C" __declspec(dllimport) #endif
もうすぐ冬なので雪を作りたい。
だがなかなかわかりやすいCyclesのノード構成図が見当たらない。
この絵の床は
https://www.packtpub.com/books/content/creating-ice-and-snow-materials
のiceを途中までやったのだがテクスチャが必要と言われ断念。
ゆきだるまのほうは自前で何かしらやった結果。
てか、iceこれで十分じゃね?(ちょっと変えてある)
template<typename T> struct coord { T x; T y; T z; coord() {} coord(const T _x, const T _y, const T _z) { x = _x; y = _y; z = _z; } template<typename U> coord<T>& operator=(const coord<U>& src) { x = src.x; y = src.y; z = src.z; return *this; } };
このような構造体があったとして、こいつにoperatorを定義するときにいつも悩むのが戻り値の型である。
template<typename T, typename U> double operator-(const coord<T>& s, U v) { typedef decltype(s.x - v) Type; return coord< Type >( static_cast<Type>(s.x - v), static_cast<Type>(s.y - v), static_cast<Type>(s.z - v) ); }
このように型を決め打ちしてしまうと、TもUもintなのにdoubleが返ってくることになったり、long doubleが入ってきたりすると潰れてしまう。
BoostにはBOOST::TYPEOFなるものがあるらしいが、このためにBoostを使うのは論外だ。
Boostにあるということはメタメタすればいけるんだろうが、これもやりたくない。
ここで思い出したのだが、今は仕事でもVC++2015を使っている。こいつのC++11対応はMicrosoftにしては良い線行っている。
autoとdecltypeを使えば、以下のように書ける。
template<typename T, typename U> auto operator-(const coord<T>& s, U v) { typedef decltype(s.x - v) Type; return coord< Type >( static_cast<Type>( s.x-v ), static_cast<Type>( s.y-v ), static_cast<Type>( s.z-v ) ); }
やはり、ターゲットプラットフォームに問題がないなら、Visual C++のバージョンは2015以降を使うことを人類の義務にすべきだ。トランプよ法律作れ。
Blender/Cycles 練習 作品No.00002 秋の草原と紅葉
早くしないと冬になってしまうのでとりあえず秋っぽいものを作る。
といっても木はSapling、草はHair、背景はSky Textureなので何一つ自分で作ってない。
家電量販店(爆買いでも減益・赤字)
http://blog.livedoor.jp/nevada_report-investment/archives/4949260.html
家電量販店の業績が惨憺たる状況になっています。
中国人等の「爆買い」と言われる巨大需要を入れましても、業績悪化が進んでいるのです。コジマ 63億円の赤字(前期は10億円の黒字・予想は4.4億円の黒字) 無配転落へ
ビックカメラ 68億円の黒字(31%減益:予想は102億円)本来なら増額修正してもおかしくはない環境ですが、中国人の「爆買い」を入れても上記のような状況になっているのです。
これは日本人、特に地方での販売不振が深刻化しているからだと言え、このため家電量販店は都心に店舗を集中させてきていますが、中国人による「爆買い」が減少しつつあると言われており、家電量販店は更なる業績下方修正となるかも知れません。
リンクとはあまり関係ないのだが、地方の電気屋の品数の少なさはある意味仕方がないことではあるが、それを補う努力があまりされていない。
私がiPadを下見に行ったときの話。まず、iPadがネットにつながっていない。あんなネットありきの機械でネットにつながっていないなどふざけた話である。ダミーのウェブサイトすら用意していないので、Safariの使い勝手を確かめることすらできない。
あるいは、タッチペンの性能が売りのノートパソコンにも関わらず、付属しているClipStudioを起動できる電気屋を見たことがない。私自身はそんなに使うソフトではないのだが、ペン性能を確認したいときにPaintはないだろう。Fresh Paintは薄くて太い線しかかけないし(ちなみにこのあたりは新宿でも大差ない)
ネット通販がこれだけ普及している以上、電気屋は「来ていただく」立場に立たなければならないのではないか。こちらとしては、せっかく「行ってやって」も、広告の内容程度の事しかわからないのでは、利用価値がない。
じゃあどうすればいいかと言うと、私は、体験型のサービスを要求したい。行くことに意味を持たせなければならないからだ。実物を「見る」だけでも価値はあるが、通販でボタン一つで運んでくれる手軽さにそうそう勝てるものではない。
まず、あのうるさいBGMとテレビの垂れ流しをやめるか、スイッチ一つで切れるようにしておく。
その上で、例えば洗濯機を見に来た人には、実際に動かしてどの程度の音が出るか、振動はどうかを比較体験してもらう。オーディオ機器であれば静かな場所で聞くというのは特に重要なはずだ。勿論、自宅の個室と電気屋の開放的な空間では全く違うのだろうが、それはまあいい。
あるいは、マウス・キーボードコーナーにPCを置いておき、USBをさして試用できるといい。盗難防止措置はなんとかしろ。
既にそれが行われている分野もある。例えば蛍光灯だ。あれはつけておくだけだから簡単なのだろう。
だがパソコンはそれだけでは不十分だ。Windowsデスクトップが表示されているだけでは何の情報にもならない。Microsoftがいくらユーザーエクスペリエンス(利用者体験)を高らかに叫んでも、電気屋で体験させてもらえないのは片手落ちと言うものだ。
電気屋に行く、と言う行為そのもののせいで、交通費+時間だけでネット通販の割引率が吹き飛んでしまうという事だって珍しくない。それでも店舗に足を運ぶのは、パンフレットではどうにもわからないものを確認したいからに他ならない。
それとも、インター何とかって横文字はよくわからんですじゃという年寄りばかり相手にするつもりだろうか。あの方々がが新発売のスマホに行列を作る姿はなかなか想像が難しいのだが。