2012-07-23 63 views
5

Tôi đang xử lý một trong các vấn đề về ứng dụng của mình. Ở đây vấn đề tôi đang phải đối mặt là có một số chức năng mà tôi cần phải gọi bằng cách sử dụng con trỏ của một đối tượng lớp.Địa chỉ của một đối tượng trong C++ và các thành viên của nó

Nhưng vấn đề chính là tôi không có một con trỏ lớp với tôi, thay vào đó tôi có một giá trị biến thành viên (cho phép nói một danh sách các giá trị của nó). sau này tôi đã làm một thử nghiệm nhỏ với các mã dưới đây.

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; 
} 

Các COutput việc thực hiện là:

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

Bây giờ nghi ngờ của tôi là:

Có đảm bảo rằng địa chỉ của biến thành viên lớp luôn trỏ tới địa chỉ của đối tượng? Tôi có thể sử dụng địa chỉ này trong trường hợp tôi cần sử dụng con trỏ để gọi các chức năng api lõi khác không?

Tôi thấy điều này khi tôi googled?

(C1x §6.7.2.1.13: "Con trỏ đến đối tượng cấu trúc, được chuyển đổi phù hợp, điểm thành thành viên ban đầu của nó ... và ngược lại. Có thể có đệm không tên trong đối tượng cấu trúc, nhưng không bắt đầu của nó. ")

điều này đúng ngay cả trong trường hợp của C++ và các lớp học?

+1

Xem macro bù đắp. Chỉ dành cho các loại POD! –

+0

Đối với mỗi loại lớp, mọi thành viên dữ liệu sẽ có giá trị bù đắp cố định.Đây không phải là địa chỉ bắt đầu của đối tượng khi trình biên dịch đặt một số thứ ở trên cùng. Nhưng điều này sẽ khác khi bạn có các hàm ảo vì trình biên dịch cũng cần đặt vptr * vào đối tượng. Vì vậy, tôi không thực hành tốt thường để làm theo cách này. – madu

+1

có thể liên quan: http://stackoverflow.com/questions/8240273/a-portable-way-to-calculate-pointer-to-the-whole-structure-using-pointer-to-a-fi – user396672

Trả lời

7

Có đảm bảo rằng địa chỉ của biến thành viên lớp luôn trỏ đến địa chỉ của đối tượng không?

No. Trong C++, có khả năng công cụ trước thành viên đầu tiên (đặc biệt cho các lớp học có nguồn gốc và các lớp đa hình). Chính xác những gì có được thực hiện được xác định.

Tôi có thể sử dụng địa chỉ này trong trường hợp tôi cần phải sử dụng con trỏ để gọi các chức năng api lõi khác không?

Không, và bạn không cần phải: bất cứ khi nào bạn có quyền truy cập vào thành viên, bạn cũng có quyền truy cập this, không?

+0

Thật không may Tôi có một con trỏ đến lá cuối cùng của cây tôi chỉ có khóa cha và sử dụng khóa cha tôi có thể nhận được danh sách các trẻ em mà nó có đó là một danh sách và đó là một meber của class.This có thể được nói như là một cây nhưng nó không phải là một cây thực tế thực hiện. – Vijay

+0

@peter Điều đó không rõ ràng. Nhưng câu trả lời vẫn giữ nguyên. Bạn * không thể * sử dụng một con trỏ đến thành viên như một con trỏ đến lớp. Làm như vậy dẫn đến mã C++ không hợp lệ sẽ phá vỡ. –

1

Điều này cũng đúng đối với các lớp trừ khi chúng có bất kỳ chức năng ảo nào. Ngoài ra, bạn nên cẩn thận nếu bạn có thừa kế (không chắc chắn chính xác các quy tắc có đó).

Nói chung, đây là một ý tưởng tồi. Tại sao bạn muốn làm điều đó? Bạn dựa vào cấu trúc của lớp (tức là mã của bạn sẽ phá vỡ nếu bạn vô tình thêm một thành viên trước tuổi) và bạn cho đi gói gọn (không có lớp nào khác phải có con trỏ đến tuổi nào, vì nó là riêng tư - bạn sẽ làm rò rỉ bạn đại diện đối tượng).

Btw: Bạn có phải là lập trình viên Java không? Nhà xây dựng của bạn trông giống như bạn đang có, vì bạn không khởi tạo đối tượng của bạn một cách chính xác. Bạn nên làm như sau:

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

(nếu không trình biên dịch đầu tiên sẽ gọi các contstructors mặc định của int và string và sau đó gọi operator = trên chúng - điều này không hiệu quả).

Các vấn đề liên quan