## 17.3 構築と初期化

標準ストリームクラスの仮想基底クラスは、`basic_ios<charT,Traits>` です。C++ では、仮想基底クラスは最新の派生クラスで初期化されます。つまり、基底クラス `basic_ios<charT,Traits>` は、新しい `odatstream` クラスで初期化されます。現在、クラス `basic_ios<charT,Traits>` は唯一の公開コンストラクタであり、ストリームバッファまでのポインタが必要です。クラス `basic_ios<charT,Traits>` にはストリームバッファまでのポインタがあり、`basic_ios` オブジェクトの作成時に初期化する必要があるので、基底クラスに対するストリームバッファの提供方法を記述しておきます。それには次の 2 通りの方法があります。

- ファイルストリームや文字列ストリームクラスからの派生。すなわち、クラス `(i/o)fstream<>` やクラス `(i/o)stringstream<>`
- ストリームクラス `basic_(i/o)stream<>` からの派生

### 17.3.1 (i/o)fstream<> や (i/o)stringstream<> などのファイルストリームや文字列ストリームクラスからの派生

ファイルと文字列のストリームクラスには、ストリームバッファデータメンバーがあり、各ストリームバッファにポインタを設定して、仮想基底クラスの初期設定値を監視しています。これらのクラスから派生させる場合は、ファイルや文字列のストリームのコンストラクタによって上書きされるため、新たなストリームバッファポインタを作成する必要はありません (階層のどこにあっても、仮想基底クラスは非仮想基底クラスより先に作成されます)。

>     template <class charT, class Traits=char_traits<charT> >
>     class MyOfstream : public basic_ofstream<charT,Traits> {
>      public:
>        MyOfstream(const char* name)
>        : basic_ios<charT,Traits>(streambufptr)
>        , basic_ofstream<charT,Traits>(name) {}
>        // . . .
>     };

構築順序は次のとおりです。

>     basic_ios(basic_streambuf<charT,Traits>*)
>     basic_ofstream(const char*)
>     basic_ostream(basic_streambuf<charT,Traits>*)
>     ios_base()

`basic_ios` のコンストラクタによって設定されたストリームバッファポインタは、`basic_ofstream` のコンストラクタによって上書きされます。

この矛盾を解決するために、クラス `basic_ios<charT,Traits>` には、公開コンストラクタ以外に限定公開のデフォルトコンストラクタがあります。このデフォルトのコンストラクタは、ストリームバッファポインタを必要としますが、何も処理しません。その代わり、限定公開の初期設定関数 `basic_ios<charT,Traits>::init()` があり、これは `basic_ios<charT,Traits>` から派生させた任意のクラスから呼び出すことができます。この関数の場合、`basic_ios<>` 基底クラスは、実際にストリームバッファを提供するストリームクラス (この例では、`basic_ofstream<charT,Traits>`) によって初期化され、限定公開の `init()` 関数が呼び出されます。

>     template <class charT, class Traits=char_traits<charT> >
>     class MyOfstream : public basic_ofstream<charT,Traits> {
>      public:
>        MyOfstream(const char* name)
>        : basic_ofstream<charT,Traits>(name) {}
>        // . . .
>     };

構築と初期化の順序は、次のとおりです。

>     basic_ios()
>     basic_ofstream(const char*)
>     basic_ostream()
>     which calls:
>       basic_ios<charT,Traits>::init(basic_streambuf<charT,Traits>*)
>     ios_base()

### 17.3.2 ストリームクラス basic_(i/o)stream<> からの派生

ストリームクラスからの派生スキーマは、ストリームバッファに常にポインタを提供する必要があるという点で少し異なります。これは、ファイルや文字列のストリームクラスと異なり、ストリームクラスにストリームバッファがないためです。たとえば、出力ストリームから派生したクラスは、次のようになります。

>     template <class charT, class Traits=char_traits<charT> >
>     class MyOstream : public basic_ostream<charT,Traits> {
>      public:
>        MyOstream(basic_streambuf<charT,Traits>* sb)
>        : basic_ostream<charT,Traits>(sb) {}
>        // . . .
>     };

ストリームの作成に必要なストリームバッファを提供する方法は、次のようにいくつかあります。

- ストリームの作成前に、別途ストリームバッファを作成する。ファイルバッファが独立したオブジェクトとして作成され、派生ストリームに使用される簡単な例を次に示します。

  >     basic_filebuf<char> strbuf;
  >     strbuf.open("/tmp/xxx");
  >     MyOstream<char> mostr(&strbuf);
  >     mostr << "Hello world\n";

- 別のストリームのストリームバッファを利用する。次の例では、標準エラーストリーム `cerr` のストリームバッファを「流用」しています。

  >     MyOstream<char,char_traits<char> > mostr(cerr.rdbuf());

  >     mostr << "Hello world\n";

  ここで、ストリームバッファは `mostr` と `cerr` が共有していることに注意してください (詳細は、13.3 節を参照してください)。

- データメンバーとして、または継承して、派生ストリームにストリームバッファを組み込む。新しいストリームバッファ型を新しいストリーム型と共に使用する場合に適した方法です。

Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。

OEM リリース, 1998 年 6 月