7

これは多くの質問が寄せられていることは知っていますが、私が見つけた唯一の答えは、(int *)などを使用してconst-nessが実際にキャストされたときでした。キャストが含まれていないのに、const修飾子がconstオブジェクトのポインター型メンバー変数で機能しないのはなぜですか?

#include <iostream>

class bar {
public:
    void doit()       { std::cout << "    bar::doit() non-const\n"; }
    void doit() const { std::cout << "    bar::doit() const\n"; }
};

class foo {
    bar* mybar1;
    bar mybar2;
public:
    foo() : mybar1(new bar) {}
    void doit() const {
        std::cout << "foo::doit() const\n";
        std::cout << "  calling mybar1->doit()\n";
        mybar1->doit();  // This calls bar::doit() instead of bar::doit() const
        std::cout << "  calling mybar2.doit()\n";
        mybar2.doit(); // This calls bar::doit() const correctly
    }
    // ... (proper copying elided for brevity)
};

int main(void)
{
    const foo foobar;  // NOTE: foobar is const
    foobar.doit();
}

上記のコードは、次の出力を生成します(gcc 4.5.2およびvc100でテスト済み)。

foo :: doit()const
  mybar1-> doit()を呼び出す
    bar :: doit()non-const <-なぜですか?
  mybar2.doit()を呼び出す
    bar :: doit()const
4

3 に答える 3

15

foo インスタンスが const の場合、そのデータ メンバーも const ですが、これはポインターに対しては、最初に考えるよりも異なる方法で適用されます。

struct A {
  int *p;
};

A const obj;

obj.p の型は、int const * ではなく、int * const です。つまり、定数 int へのポインターではなく、int への定数ポインターです。

別の見方をするために、関数から始めましょう。

template<class T>
T const& const_(T const &x) {
  return x;
}

ここで、A インスタンスがあり、それを const にするとします。各データ メンバーに const_ を適用すると想像できます。

A nc;
// nc.p has type int*.
typedef int *T;  // T is the type of nc.p.

T const &p_when_nc_is_const = const_(nc.p);
// "T const" is "int * const".

const T &be_wary_of_where_you_place_const = const_(nc.p);
// "const T" is "int * const".
// "const T" is *not* "const int *".

変数 be_wary_of_where_you_place_const は、「const を追加する」ことは、型のリテラル テキストに「const」を追加することと同じではないことを示しています。

于 2011-05-06T22:30:05.757 に答える
1

この場合、私は自分の質問に答えるつもりです。Fred Nurk の答えは正しいですが、「理由」を実際に説明していません。mybar1*mybar1は異なります。最初は実際のポインタを参照し、後者はオブジェクトを参照します。ポインターは const です (foo の const-ness によって義務付けられているため、実行できませんmybar1 = 0) が、指しているオブジェクトではありません。宣言する必要があるためですconst bar* mybar1。この宣言は、foo オブジェクトが const である (つまり、ポインターが const であり、オブジェクトを指していない) 場合bar* mybar1と同等です。bar* const mybar1

于 2011-05-06T23:13:00.457 に答える
0

デフォルトでは、C++ はいわゆるビットごとの constness を提供します。つまり、オブジェクトの単一ビットが変更されていないことが保証されるため、ポインターのアドレスをチェックするだけです。

詳細については、S. Meyers の著書「Effective c++」を参照してください。

于 2014-04-30T16:05:37.717 に答える