Help us understand the problem. What is going on with this article?

ラッパークラス開発で学ぶ実践C++ その1 準備

More than 3 years have passed since last update.

このドキュメントは連載の初回です。

はじめに

C++で古代のAPI 1 のラッパークラス2を開発します。
その流れの中で、 C++ のうれしさや基本作法を紹介しつつ、クラスの作り方を学んでみよう、という企画です。
言っても、C++11以降を使わ(え)ないので、せいぜい中世くらいまでしかフォローできません。

一応対象は C++ 初級者~ですが、言葉足らずなので全くの初心者はついてこれないかもしれません。

  • 教科書でC++勉強してみたけど、実戦でどう使えばいいかイマイチピンとこない。
  • 今でも C を使っているけど本当はC++が気になっている。
  • 教科書で勉強するより、体で覚えるほうが好き。

という方のお役に立てるかもしれません。

今は素晴らしい文書が山のようにあるので、知識・技術の解説はそちらに任せます。
「実践」というくらいなので、手を動かしつつ読んでもらえると幸いです。

お題 : win32 TLS

Windows API からスレッドローカルストレージ (TLS)のAPI をラッピングしてみます。3

C++11以降はキーワード一発 で使える TLS ですが、古代は API で操作していました。
なのでC++11以降の機能は使いません。4

今回はこちらのサンプルコードを教材として利用させていただきました。

もしTLS知らなかったら、軽く目を通しておいて下さい。

static_cast

個人的に C から来た人に一番最初に憶えてほしいのが static_cast です。
下記のリンク先は、C++キャストの種類や危険性、Cスタイルキャストの邪悪さについて説明しています。

C++キャストはいくつもありますが、ここでは static_cast だけ憶えて下さい。
もし static_cast でコンパイラに怒られることがあったら、他のキャストを検討する前に設計の良し悪しを疑って下さい。

サンプルコードのCスタイルキャストを、static_cast に置き換えてみましょう。
(置き換え後のコードは最後にまとめてお見せします。)

printf をやめてみよう

みんな、そんなに printf が好きですか? iostream 嫌いですか?

iostream がときどき異常に複雑になることは認めます。

ですが printf の %d , %s 等と、引数の型・数・順をぴったり合わせないといけないって、面倒だし、何より安全とは言えませえんよね。
片方直すとき、もう片方も直さにゃならんし。

printf( "TlsAlloc() Failed. gle=%u\n", GetLastError() );

やめて

std::cout << "TlsAlloc() Failed. gle=" << GetLastError() << std::endl;

に慣れてみませんか?

型指定いらないのって、慣れると便利ですよ。
クラス専用の出力を自前で定義できるんですが、これができるとちょっとうれしくなってくるかも。そのうち紹介します。


ということで、教材サンプルコードに手を入れた結果です。

#include <windows.h> 
#include <iostream>   // stdio.h の代わり

// 内容を main() から分離しました。
int tls_test()
{
    DWORD dwIndex = TlsAlloc();
    if (TLS_OUT_OF_INDEXES == dwIndex) {
        std::cout << "TlsAlloc() Failed. gle=" << GetLastError() << std::endl;
        return 1;
    }
    std::cout << "TlsAlloc returned " << dwIndex << std::endl;

    char szMsg[] = "Hello, World\n";
    if (!TlsSetValue(dwIndex, szMsg)) {
        std::cout << "TlsSetValue Failed. glt = " << GetLastError() << std::endl;
        return 1;
    }

    char* szRet = static_cast<char*>(TlsGetValue(dwIndex));
    if (!szRet) {
        std::cout << "TlsGetValue Failed." << std::endl;
        return 1;
    }
    std::cout << szRet << std::endl;

    if (!TlsFree(dwIndex)) {
        std::cout << "TlsFree Failed." << std::endl;
        return 1;
    }
    return 0;
}

int main(int argc, char* argv[]) 
{
    int ret = tls_test();
    // VS で F5 押した時一瞬で終わっちゃわないようにする。
    char c;
    std::cin >> c;

    return ret;
}

実際に書いて実行してみてください。以下が出力結果です。

TlsAlloc returned 1
Hello, World

確保して set して get して解放する。
教材にはちょうどいい基本を押さえたAPIですね。

次回以降、このサンプルコードをリファクタリングしながらラッパークラスを開発していきます。



  1. Win32 API とか POSIX API とか 

  2. wrapper class. あるAPI群を包み込んで(wrap)隠蔽し、使いやすくしたクラスのことをこう呼ぶことにします。一般的な用語だと思ってたんだけど、検索すると Java のプリミティブラッパークラスばかりヒットするので、念のためここで断っておきます。 

  3. SSLの親戚のことではありません 

  4. thread_local 使えで終わってしまいますから。 

uctakeoff
「車や飛行機に憧れる気持ちはよくわかりますが、その前にまずはその手に持っている石オノを置きましょうか.話はそれからです.」
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした