2012-07-23 8 views
5

私のアプリケーションの問題の1つに取り組んでいます。 ここで私が直面している問題は、クラスオブジェクトのポインタを使って呼び出す必要があるいくつかの関数があることです。C++のオブジェクトのアドレスとそのメンバー

しかし、主な問題は、私はクラスポインタを持っていません、代わりに私はメンバ変数の値を持っています(その値のリストを言うことができます)。私は以下のコードで小さなテストを行った。

using namespace std; 

class Person { 
public: 
     Person(string name, int age) { 
      this->name = name; 
      this->age = age; 
     } 
     string getName() { 
      return name; 
     } 
     int getAge() { 
      return age; 
     } 
     void Print() 
     { 
     printf("This address is %x\n",this); 
     printf("age adress is %x\n",&age); 

     } 
private: 
     int age; 
     string name; 

}; 

int main() { 
     cout << "Creating a person..." << endl; 

Person *johnDoe=new Person("John Doe", 25); 
     cout << "Person's name: " << johnDoe->getName() << endl; 
     cout << "Person's age: " << johnDoe->getAge() << endl; 
     johnDoe->Print(); 
     delete johnDoe; 
     return 0; 
} 

実行のcoutputされています。今、私の疑いがある

> ./a.out 
Creating a person... 
Person's name: John Doe 
Person's age: 25 
This address is 72918 
age adress is 72918 

が、それはクラスのメンバ変数のアドレスは常にオブジェクトのアドレスを指していることを保証しますか? 他のコアAPI関数を呼び出すためにポインタを使用する必要がある場合に備えて、このアドレスを使用できますか?

私はグーグルでこれを見ましたか?

(C1x§6.7.2.1.13: "適切に変換された構造体オブジェクトへのポインタは、その最初のメンバを指します...その逆もあります。構造体オブジェクト内で名前なしのパディングがあります。 )」

これは、C++やクラスの場合でも同じですか?

+1

offsetofマクロを参照してください。 PODタイプのみ! –

+0

各クラスタイプについて、すべてのデータメンバーは固定オフセット値になります。これは、コンパイラがいくつかのものを上に置くので、オブジェクトの開始アドレスではありません。しかし、これは、コンパイラがvptr *をオブジェクトに入れる必要があるため、仮想関数がある場合とは異なります。だから私はこのようにするのが一般的に良い習慣ではない。 – madu

+1

が関連している可能性があります:http://stackoverflow.com/questions/8240273/a-portable-way-to-calculate-pointer-to-the-whole-structure-using-pointer-to-a-fi – user396672

答えて

7

クラスメンバ変数のアドレスが常にオブジェクトのアドレスを指していることは保証されていますか?

いいえ。C++では、最初のメンバー(特に派生クラスと多相クラス)の前には、潜在的に不具合があります。そこには実装が定義されています。

他のコアAPI関数を呼び出すためにポインタを使用する必要がある場合は、このアドレスを使用できますか?

いいえ、必要はありません。メンバーにアクセスするたびにthisにアクセスできますか?

+0

残念ながら、私はツリーの最後の葉へのポインタを持っています。私は親キーしか持っていませんし、親キーを使っています。それはリストであり、クラスのmeberです子供のリストを得ることができます。実際のツリー実装ではありません。 – Vijay

+0

@peterそれは不明です。しかし答えは同じです。クラスへのポインタとしてメンバーへのポインタを使用することはできません。そうすると無効なC++コードが破損します。 –

1

これは仮想関数がない限り、クラスでも同様です。また、継承がある場合は注意が必要です(ルールがどれくらい正確に存在するかはわかりません)。

一般的に、これは悪い考えです。なぜあなたはそれをしたいのですか?あなたはクラスの構造に頼っている(つまり、あなたが偶然に年齢の前にメンバーを追加するとあなたのコードは壊れます)、カプセル化を放棄します(プライベートなので、オブジェクト表現)。

Btw:あなたはJavaプログラマですか?あなたのオブジェクトは正しく初期化されていないので、コンストラクタはあなたのように見えます。あなたはこのようにそれを実行する必要があります。

Person(String n, int a) : age(a), name(s) {} 

(そうでない場合、コンパイラは最初のint型と文字列のデフォルトcontstructorsを呼び出しますし、それらに=演算子を呼び出す - これは効率的ではありません)。

関連する問題