C++ 移行ガイド ホーム目次前ページへ次ページへ索引


第 2 章

互換モードの使い方

この章では、C++ 4 コンパイラ用に記述されたコードをコンパイルする方法について説明します。

互換モード

次のコンパイラオプションは、ともに互換モードを指示します。

-compat
-compat=4

例:

example% CC -compat -O myfile.cc mylib.a -o myprog

以降で説明するように、互換モードにおいては、C++ 4 と Sun WorkShop 6 C++ コンパイラの間に多少の使用方法の違いがあります。

互換モードで有効なキーワード

互換モードでは、新しい C++ キーワードの一部がキーワードとして認識されます。ただし、これらのキーワードの大部分は、次の表に示すようにコンパイラオプションを使用して無効にすることができます。しかし、コンパイラオプションを使用するよりも、ソースコードを変更してこれらのキーワードを使用しないようにすることをお勧めします。

表 2-1   互換モードで有効なキーワード
キーワード 無効にするためのオプション
explicit -features=no%explicit
export -features=no%export
mutable -features=no%mutable
typename なし


typename キーワードを無効にすることはできません。表 3-1 に示すその他の新しい C++ キーワードは、互換モードではデフォルトで無効になります。

言語の意味

Sun WorkShop 6 C++ コンパイラでは、C++ 言語の一部の規則について適用機能が強化されています。旧式の構文に対する基準も厳しくなっています。

新しいバージョンの C++ コンパイラをリリースする際に、旧式の構文のサポートを中止するということは、以前からの方針 (マニュアルに記載) でした。しかし、C++ 4 で旧式の構文に関する警告を有効にしてコンパイルすると、かなり前の C++ コンパイラでは受け入れられてきたが、実際には不正であったコードが見つかることがあります。旧式の構文とは主として、アクセス規則 (非公開や限定公開) に違反した構文や、型一致規則に違反した構文、コンパイラが生成した一時変数を参照パラメータの対象として使用した構文などです。

新たに適用されることになった規則は、次のとおりです。

コピーコンストラクタ

オブジェクトを初期化するとき、あるいはクラスの型の値を渡したり返したりするとき、コピーコンストラクタはアクセス可能でなければならない。

class T {
T(const T&); // 非公開
};
void f1(T t) { } // エラー、T が渡されない
T f2() { T t; return t; } // エラー、T が返されない

解決策: コピーコンストラクタをアクセス可能にしてください。通常は、公開にします。

static 記憶クラス

static 記憶クラスは、型ではなくオブジェクトおよび関数に適用される。

static class C {...};   // エラー、ここでは static を使用できない
static class D {...} d; // OK、d は static になる

解決策: この例では、クラス C の static キーワードは意味がないので削除してください。

operator newoperator delete

new でオブジェクトを割り当てるときは、対応する operator delete がアクセス可能でなければならない。

class T {
void operator delete(void*); // 非公開
public:
void* operator new(size_t);
};
T* t = new T; // エラー、operator delete にアクセスできない

解決策: 演算子 delete をアクセス可能にしてください。通常 delete は公開アクセスであると想定されています。

クラスメンバーでない operator new または operator deletestatic 宣言することはできない。

static void* operator new(size_t); // エラー

解決策: 関数を大域型にしてください。

delete 式にカウントを入れることはできない。

delete [5] p; // エラー、delete [] p; を使用すること

new const

const オブジェクトを new で割り当てる場合は、オブジェクトを初期化する必要がある。

const int* ip1 = new const int;    // エラー
const int* ip2 = new const int(3); // OK

条件式

C++ 標準は条件式の規則に変更を導入しました。Sun WorkShop 6 C++ コンパイラは、標準モードと互換モードの両方で新しい規則を使用します。詳細は、「条件式」を参照してください。

デフォルトのパラメータ値

多重定義演算子や関数へのポインタにデフォルトのパラメータ値を設定することはできない。

T operator+(T t1, T t2 = T(0) );   // エラー
void (*fptr)(int = 3); // エラー

解決策: 他の方法でコーディングする必要があります。一般的には、関数または関数へのポインタ宣言を追加することが考えられます。

main() の戻り値の型

main 関数が返す値の型は、int でなければならない。

void main(){ ... } // エラー

解決策: main の戻り値の型を int にしてください。return 文を追加する必要はありません。追加した場合、return 文は int 値を返す必要があります。

末尾にコンマを使用する

関数引数リストの末尾にコンマを使用することはできない。

f(int i, int j, ){ ... } // エラー

解決策: 余分なコンマを削除してください。

const 値またはリテラル値を渡す

const 以外の参照パラメータに const 値またはリテラル値を渡すことはできない。

void f(T&); 
extern const T t;
void g() {
f(t); // エラー
}

解決策: 上記の関数によってパラメータが変更されない場合は、const を参照するように const 宣言 (この例では const T&) を変更してください。関数によってパラメータが変更される場合、パラメータに const やリテラル値を渡すことはできません。代りに、const 以外の一時変数を明示的に作成し、それを渡します。詳細は、「文字列リテラルと char*」を参照してください。

関数へのポインタと void* 間の変換

C++ コンパイラは互換モードと標準モードのどちらでも、+w2 オプションが指定された場合に、 関数へのポインタと void* 間での暗黙的および明示的変換に対して警告を出します。 コンパイラは、どちらのモードでも、多重定義された関数呼び出しを解釈処理するときには、暗黙的な変換を認識しません。詳細は、「関数ポインタと void*」を参照してください。

enum

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) を使用すること
};

constvolatile 修飾子

関数に引数を渡すとき、および変数を初期化するとき、ポインタに対する constvolatile 修飾子は正しく対応している必要がある。

void f(char *); 
const char* p = "hello";
f(p);        // エラー、const ではない char* に const char* を              渡すことはできない 

解決策: ポイント先の文字列が関数によって変更されない場合は、パラメータを const char* で宣言してください。ポイント先の文字列が変更される場合は、文字列の const ではないコピーを作成して、そのコピーを渡してください。

入れ子の型

クラス修飾子がないと、包含するクラスの外側から入れ子の型にアクセスすることはできない。

struct Outer {
struct Inner { int i; };
int j;
};
Inner x; // エラー、Outer::Inner を使用すること

クラステンプレートの定義と宣言

クラステンプレートの定義と宣言中では、山かっこ < > で囲まれた型引数が付いたクラスの名前は無効でしたが、バージョン 4 とバージョン 5.0 の C++ コンパイラはエラーを報告しませんでした。たとえば、次のコードでは、MyClass に付けられた <T> は定義と宣言のどちらでも無効です。

template<class T> class MyClass<T> { ... }; // 定義
template<class T> class MyClass<T>;         // 宣言

解決策: 次の例のように、山かっこで囲まれた型引数をクラス名から削除します。

template<class T> class MyClass { ... }; // 定義
template<class T> class MyClass;         // 宣言

テンプレートコンパイルモデル

互換モードでのテンプレートコンパイルモデルは 4.2 のコンパイルモデルとは異なります。新しいモデルについての詳細は、3-6 ページの 3.3.5 節「テンプレートレポジトリ」を参照してください。


サン・マイクロシステムズ株式会社
Copyright information. All rights reserved.
ホーム   |   目次   |   前ページへ   |   次ページへ   |   索引