0

main.cpp の内部

class vivek
{
    int i;
    float d;
public:
    vivek()
    {
        i = 4;
        d = 4.44;
    }
    ~vivek()
    {
        cout << "destructor" << i;
    }
    int get()
    {
        return i;
    }
};

int main()
{
    vivek *viku = new vivek;
    vivek *p;

    p = viku;
    cout << (*(int*) (p));
    getchar();

    return 0;
}

上記のコードで変数 i にアクセスできますが、変数 d にアクセスする方法を知りたいです。

カプセル化に違反するため、この概念はお勧めできません..しかし、どうすればこれを行うことができるか知りたいだけですか?

4

6 に答える 6

2

ポインターを理解するためにやっていると思うので、反対票を投じる危険があります。

たぶん、あなたが期待していたのは次のようなものでした:
int * x=reinterpret_cast<int *>(p);
x++;
cout<<*reinterpret_cast<float *>(x);

どちらが機能し、おそらく遭遇するほとんどのコンパイラで機能します。ただし、このようなことをしてはいけない理由はたくさんあります。

Uses and Abuses of Access Rights必読です。

また、標準では、アクセス指定子で区切られたメンバーの順序について明確にコメントしていることにも注意してください。別のソフ回答から:

access-specifier を介在させずに宣言された (非共用体) クラスの非静的データ メンバーは、後のメンバーがクラス オブジェクト内でより高いアドレスを持つように割り当てられます。アクセス指定子で区切られた非静的データ メンバーの割り当て順序は指定されていません (11.1)。

于 2012-11-27T14:22:23.130 に答える
2

非常にハックですが、標準レイアウトの構造体であるため可能です。vivekこれは、次のことができることを意味します。

#include <iostream>

// copied from original
class vivek {
  int i;
  float d;
public:
  vivek() {i = 4; d = 4.44; }
  ~vivek() { cout<<"destructor"<<i; }
  int get() { return i; }
};

struct vivek_sneaky_accessor {
  int i;
  float d;
};

int main() {
  vivek v;
  vivek_sneaky_accessor *acc = reinterpret_cast<vivek_sneaky_accessor*>(&v);
  std::cout << acc->d;
  return 0;
}

これは、[class] ポイント 7 と 8 (標準レイアウト構造体の定義) と [class.mem] ポイント 17 と 20 (標準レイアウト構造体のレイアウト互換性) に依存しています。

免責事項私はこれを合理的な行為として推奨するつもりはありません。私はそれが実際に可能であると言っているだけです。

于 2012-11-27T14:14:30.147 に答える
1

言語弁護士によって反対票を投じられる危険を冒して、興味深いかもしれないことを願って、ハッカーのちょっとしたアドバイスを以下に示します。プライベート メンバーは、クラスおよびクラスのフレンドの外部からアクセスするためのものではありません。ただし、クラスのこれらのメンバー フィールドに絶対にアクセスする必要がある場合は、次のようなハックが機能する可能性があります。

#include <iostream>

class vivek {
    int   i;
    float d;

  public:
    vivek() : i(4), d(4.44) {}
    ~vivek() {}
};

int main()
{
    vivek viku;
    struct badhack {
        int   i;
        float d;
    } *h = (sizeof(badhack) == sizeof viku ? (badhack*)&viku
            : ((badhack*)((char*)&viku + sizeof(void*))));
    std::cout << "i=" << h->i << ", d=" << h->d << std::endl;
}

sizeof(void*)sizeof を使用したゲームに注意してください。これは、バイトを取り、仮想メンバーが存在するクラスの最初の暗黙的なフィールドである仮想テーブルを決定する例にすぎません。そうしないと、たまたまクラスに仮想テーブルがある場合、データ オフセットが台無しになり、トリックが機能しないsizeof(void*)ため、その問題を回避するためにオフセットをバイト単位で調整します。現在、これは標準では定義されておらず、コンパイラ固有ですが、これが最も効率的な方法であるため、仮想テーブルを異なる方法で実装するコンパイラに遭遇したことはありません。

別のオプションは、次のように簡単です。

#include <iostream>

#define class struct
#define private public

class vivek {
    int   i;
    float d;

  public:
    vivek() : i(4), d(4.44) {}
    ~vivek() {}
};

int main()
{
    vivek viku;
    std::cout << "i=" << viku.i << ", d=" << viku.d << std::endl;

    return 0;
}

ただし、上記はメンバー関数では機能しない可能性が高いことに注意してください。最近のコンパイラはスマートで、アクセス レベルに応じてさまざまな方法で関数名をマングルします。

そして、誰かの命を救う必要があり、その見返りに自分の命を喜んで犠牲にする場合を除き、このようなトリックを使用しないでください.

于 2012-11-27T14:31:58.573 に答える
1

それらにアクセスしたい/必要な場合は、それらを作成してくださいpublic。それが のポイントです。つまりpublic、クラスのユーザーは、 であるものを表示および変更できますpublic

これは「カプセル化を破る」と言う人もいるでしょう。ただし、クラスがいくつかの値を保持する必要があるだけで、特別なことをする必要がない場合は、データ メンバーをパブリックにすることは問題ではありません。

于 2012-11-27T13:58:23.803 に答える
1

クラスでvivek

public:
  float getD() {
    return this -> d;
  }

そして、次のようにコードで呼び出します。

std::cout << (p -> getD()) << std::endl;
于 2012-11-27T13:54:06.197 に答える
0

オブジェクトを一連のバイトとして扱い、それらのバイトを直接いじることは確かに可能ですが、それは非常に悪い考えです。クラスとオブジェクトを持つことの要点は、データがメモリ内で実際にどのように配置されるかを考える手間を省くことです。

于 2012-11-27T14:32:30.730 に答える