この章では、C++ 4 コンパイラ用に記述したコードを C++ 5.0 で使用する方法を 説明します。
-compat -compat=4
CC -compat -O myfile.cc mylib.a -o myprog
以降で説明するように、互換モードにおいては、C++ 4 と C++ 5.0 コンパイラの間に多少の使用方法の違いがあります。
互換モードでは、新しい C++ キーワードの一部がキーワードとして認識されます。ただし、これらのキーワードの大部分は、次の表に示すようにコンパイラオプションを使用して無効にすることができます。しかし、コンパイラオプションを使用するよりも、ソースコードを変更してこれらのキーワードを使用しないようにすることをお勧めします。
表 2-1 互換モードで有効なキーワード
キーワード |
無効にするためのオプション |
---|---|
explicit |
-features=no%explicit |
export |
-features=no%export |
mutable |
-features=no%mutable |
typename |
なし |
typename キーワードを無効にすることはできません。表 3-1 に示すその他の新しい C++ キーワードは、互換モードではデフォルトで無効になります。
C++ 5.0 コンパイラでは、C++ 言語の一部の規則について適用機能が強化されています。旧式の構文に対する基準も厳しくなっています。
新しいバージョンの C++ コンパイラをリリースする際に、旧式の構文のサポートを中止するということは、以前からの方針 (マニュアルに記載) でした。しかし、C++ 4 で旧式の構文に関する警告を有効にしてコンパイルすると、かなり前の C++ コンパイラでは受け入れられてきたが、実際には不正であったコードが見つかることがあります。旧式の構文とは主として、アクセス規則 (非公開や限定公開) に違反した構文や、型一致規則に違反した構文、コンパイラが生成した一時変数を参照パラメータの対象として使用した構文などです。
新たに適用されることになった規則は、次のとおりです。
オブジェクトを初期化するとき、あるいはクラスの型の値を渡したり返したりするとき、コピーコンストラクタはアクセス可能でなければならない。
class T { T(const T&); // 非公開 }; void f1(T t) { } // エラー、T が渡されない T f2() { T t; return t; } // エラー、T が返されない
解決策: コピーコンストラクタをアクセス可能にしてください。通常は、公開にします。
static 記憶クラスは、型ではなくオブジェクトに適用されます。
static class C {...}; // エラー、ここでは static を使用できない static class D {...} d; // OK、d は static になる
解決策: この例では、クラス C の static キーワードは意味がないので削除してください。
new でオブジェクトを割り当てるときは、対応する operator delete がアクセス可能でなければならない。
class T { void operator delete(void*); // 非公開 public: void* operator new(size_t); }; T* t = new T; // エラー、operator delete にアクセスできない
解決策: operator delete をアクセス可能にしてください。通常は、公開にします。
多重定義演算子や関数へのポインタにデフォルトのパラメータ値を設定することはできない。
T operator+(T t1, T t2 = T(0) ); // エラー void (*fptr)(int = 3); // エラー
解決策: 他の方法でコーディングする必要があります。一般的には、関数または関数へのポインタ宣言を追加することが考えられます。
void main(){ ... } // エラー
解決策: main の戻り値の型を int にしてください。return 文を追加する必要はありません。追加した場合、return 文は int 値を返す必要があります。
const 以外の参照パラメータに const 値やリテラル値を渡すことはできない。
void f(T&); extern const T t; void g() { f(t); // エラー }
解決策: 上記の関数 によってパラメータが変更されない場合は、const を参照するように const 宣言 (この例では const T&) を変更してください。関数によってパラメータが変更される場合、パラメータに const やリテラル値を渡すことはできません。代りに、const 以外の一時変数を明示的に作成し、それを渡します。詳細は、「文字列リテラルと char*」を参照してください。
クラスメンバーになっていない operator new、または operator delete を static 宣言することはできない。
static void* operator new(size_t); // エラー
解決策: 関数を大域型にしてください。
enum 型のオブジェクトを初期化したり、enum 型のオブジェクトに値を代入する場合は、その値も enum 型でなければならない。
enum E { one = 1 }; E e1 = 1; // エラー、int で E を初期化することはできない E e2 = E(1); // キャストで解決
解決策: キャストを使用してください。
#undef を間に入れずにマクロを別の値に再定義することはできない。
#define count 1 #define count 2 // エラー
解決策: #define 文の一方を削除するか、2 つ目の #define 文の前に #undef count 文を挿入してください。
メンバー初期化リスト中に暗黙の基底クラス名を入れる旧式の C++ 構文を使用することはできない。
struct B { B(int); }; struct D : B { D(int i) : (i) { } // エラー、B(i) を使用すること };
new で const オブジェクトを割り当てる場合は、オブジェクトを初期化する必要がある。
const int* ip1 = new const int; // エラー const int* ip2 = new const int(3); // OK
関数に引数を渡すとき、および変数を初期化するとき、ポインタに対する const と volatile 修飾子は正しく対応している必要がある。
void f(char *); const char* p =“hello”; f(p); // エラー、const ではない char* に const char* を渡すことはできない
解決策: ポイント先の文字列が関数 によって変更されない場合は、パラメータを const char* で宣言してください。ポイント先の文字列が変更される場合は、文字列の const ではないコピーを作成して、そのコピーを渡してください。