31

目的のために Qt の共有データ ポインターに似たものをラップしようとしました。

私は C++0x オプションを使用してコンパイルしています。最小限のコードは次のとおりです。

struct Data {
    int x() const {
        return 1;
    }
};

template <class T>
struct container
{
    container() {
        ptr = new T();
    }


    T & operator*() {
        puts("non const data ptr");
        return *ptr;
    }

    T * operator->() {
        puts("non const data ptr");
        return ptr;
    }

    const T & operator*() const {
        puts("const data ptr");
        return *ptr;
    }

    const T * operator->() const {
        puts("const data ptr");
        return ptr;
    }

    T* ptr;
};

typedef container<Data> testType;

void testing() {
    testType test;
    test->x();
}

ご覧のとおり、Data.x は const 関数なので、呼び出される演算子 -> は const でなければなりません。そして、非 const をコメントアウトすると、エラーなしでコンパイルされるので、可能です。それでも私の端末は次のように出力します:

「非定数データptr」

それは GCC のバグ (私は 4.5.2 を持っています) ですか、それとも欠けているものがありますか?

4

4 に答える 4

34

-nessのみが異なる 2 つのオーバーロードがある場合、コンパイラはconst、そのかどうかに基づいて呼び出しを解決します。あなたのコード例では、is notであるため、非オーバーロードが呼び出されます。*thisconsttestconstconst

これを行った場合:

testType test;
const testType &test2 = test;
test2->x();

test2isであるため、他のオーバーロードが呼び出されることがわかりますconst

于 2011-09-02T17:25:59.580 に答える
12

testは非 const オブジェクトであるため、コンパイラは最適な一致を見つけます: 非 const バージョン。static_castただし、次の方法で constness を適用できます。static_cast<const testType&>(test)->x();

EDIT:余談ですが、99.9%の確率でコンパイラのバグを見つけたと思うので、コードを再検討する必要があります。おそらく奇妙な癖があり、コンパイラは実際には標準に従っています。

于 2011-09-02T17:28:52.060 に答える
2

Data::xが定数関数かどうかは関係ありません。container<Data>呼び出される演算子は、クラスではなくクラスに属しData、そのインスタンスは定数ではないため、非定数演算子が呼び出されます。利用可能な定数演算子しかない場合、またはクラスのインスタンスが定数自体である場合、定数演算子が呼び出されます。

于 2011-09-02T17:28:05.537 に答える
0

ただしtestType、const オブジェクトではありません。

したがって、そのメンバーの非 const バージョンを呼び出します。
メソッドがまったく同じパラメーターを持っている場合、呼び出すバージョンを選択する必要があります (したがって、このパラメーター (非表示のパラメーター) を使用します)。この場合、これは const ではないため、非 const メソッドを取得します。

testType const test2;
test2->x();  // This will call the const version

非 const オブジェクトで const メソッドを呼び出すことができるため、これは x() の呼び出しには影響しません。

于 2011-09-02T17:27:44.973 に答える