Từ 1 tới 8 trên tổng số 8 kết quả

Đề tài: Lập trình C++ | Lỗi thứ tự khai báo trong Class!

  1. #1
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Mặc định Lập trình C++ | Lỗi thứ tự khai báo trong Class!

    Đây là 1 lỗi cực kì khó chịu mà theo mình nghĩ khi viết code chúng ta nên để ý đến vấn đề này, hôm nay ngòi viết mà debug gần 3 tiếng đồng hồ mới tìm ra hic hic. Nếu mọi người ai cũng biết thì bỏ qua cho mình nhé T_T. Vì thực sự mình thấy nó cũng quan trọng nên muốn ghi lại cho nhớ dai thêm 1 chút hì hì !

    Trong class nó có 1 thằng gọi là bộ khởi tạo thành viên (member-initialization) và nó sẽ khác với khi chúng ta dùng phép gán khi khởi tạo cho dữ liệu. Xét ví dụ sau :
    PHP Code:
    class Person{
    private:
     
    int age;
     
    string name;
    public:
     
    Person(int a, const string n
     {
     
    //chú ý chỗ này là phép gán chứ không phải khởi tạo. 
     
    age a
     
    name n
     }
    }; 
    Cách khởi tạo cho đúng phải là ví dụ :
    PHP Code:
    class Person
    {
    //..
    public:
     
    Person(int a, const string n) : age (a), name (n)
     {}
    }; 
    Tuy nhiên ở ví dụ trên thì sự khác biệt sẽ chẳng ảnh hưởng lắm, nhưng nó sẽ khác khi ta bắt buộc phải dùng bộ khởi tạo khi làm việc với dữ liệu là const, reference và sub-objects.
    Ví dụ :
    PHP Code:
    class Foo
    {
    private:
     
    int r// reference 
     
    const int MAX// const 
     
    Person p//object
    public:
     
    explicit Foo(intn) : r(n), MAX(100), (MAX,"John D."){}
    }; 
    Đây là cách khởi tạo hoàn toàn hợp lệ, vì nó theo đúng thứ tự mà chúng ta khai báo các dữ liệu thành viên trong class Foo. Nhưng tiếp theo chúng ta sẽ xét ví dụ sau :
    PHP Code:
    class BadFoo
    {
    private:
     
    int r;
     
    Person p;
     const 
    int MAX
    public:
     
    explicit BadFoo(intn)//Nguy hiểm đang chờ đợi
     
    r(n), MAX(100), (MAX,"John D.") {}
    }; 
    Vì chúng ta đã khai báo là
    PHP Code:
    1. int &r
    2. Person p
    ;
    3. const int Max
    Nên bộ khởi tạo sẽ tự động kích hoạt theo thứ tự sau trong cái list mà chúng ta khai báo ở dưới cho constructor :
    PHP Code:
     r(n), MAX(100), (MAX,"John D."
    và thế là thằng MAX sẽ trở thành rac, mà debug mấy lỗi này thì đúng là điên cả người T_T.
    Trong khi thứ tự đúng phải là như sau :
    PHP Code:
    explicit BadFoo(intn
     : 
    r(n), (MAX,"John D."), MAX(100) {} 

  2. #2
    Ngày gia nhập
    09 2006
    Bài viết
    711

    rox_rook đang dùng IDE & compiler nào mà gặp lỗi kỳ cục này ?

  3. #3
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Dạ, em dùng thằng Devcpp thì ok, nhưng với thằng Visual 2008 thì nó lại bắt lỗi. Em cũng không rõ có phải vậy không ? Nhưng em search trên google thì đọc được quả thật có lỗi này, thế là em sữa lại thì ok. Em cũng không biết có chắc không nữa ?

  4. #4
    Ngày gia nhập
    09 2006
    Bài viết
    711

    Anh test với VC++2008 Express, với thứ tự khai báo:
    Code:
        int &r; // reference 
        Person p; //object
        const int MAX; // const
    Thì dù có đổi thứ tự initialize list theo sau constructor như thế nào đi nữa thì vẫn bị bug, p.age = rác (0xCCCCCCCC).
    rox_rook đoán thử tại sao !

  5. #5
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Hì hì, em hiểu ý anh rùi T_T. Do thứ tự này có vấn đề :
    PHP Code:
    1. int &r
    2. Person p
    ;
    3. const int Max
    Thằng MAX chưa được khởi tạo nên dù có thế nào đi chăng nữa thì age phải là garbage .T_T ! Đưa ví dụ cũng ẩu ~~! Thanks anh đã nhắc nhở T_T
    Còn cái lỗi thứ tự này em nghĩ nó đúng đấy anh à, vì em cũng đọc thêm 1 cuốn sách C++ in action, và nó cũng đề cập đến vấn đề này.

  6. #6
    Ngày gia nhập
    08 2006
    Bài viết
    59

    Mặc định Lập trình C++ | Lỗi thứ tự khai báo trong Class!

    Tui nghĩ như vầy:

    1) Đây là lỗi của người lập trình, chớ không phải lỗi của trình biên dịch
    Theo như: http://www.devx.com/getHelpOn/10Minu...ion/17298/1954 thì
    C++ ensures that members are initialized in the order of their declaration in the class
    (C++: các thuộc tính được khởi tạo theo thứ tự đã khai báo trong class)

    class Thing
    {
    private:
    int & ref; // reference member
    const int MAX; // const member
    vector arr;
    public:
    Thing(int& r) : ref(r), MAX(100), arr (MAX) {}
    };

    Notice that the member MAX serves as arr's initializer. This is perfectly legal. C++ ensures that members are initialized in the order of their declaration in the class. If you change the member initialization list to:

    Thing(int& r) : arr(MAX), MAX(100), ref(r) {}

    The members will still be initialized in the following order: ref, MAX, and arr. However, pay attention to the members' order inside the class. Doing something like this causes unpredictable results at runtime:

    class BadThing
    {
    private:
    int & ref;
    Array arr; //wrong, should appear after MAX
    const int MAX;
    };

    The problem is that MAX hasn't been initialized when its value is passed to arr's constructor.
    (bạn rox_rook có nói là ok với Devcpp, nhưng bị lỗi với Visual 2008
    Nhưng nếu đặc tả của C++ là "ensures that members are initialized in the order of their declaration in the class" thì VC++2008 không có lỗi ở chỗ này)

    2) dấy phẩy (comma, ',') có 2 vài trò: toán tử (operator) và dấu phân cách (separator)
    Theo như http://msdn2.microsoft.com/en-us/library/zs06xbxh.aspx thì

    The comma operator has left-to-right associativity. Two expressions separated by a comma are evaluated left to right. The left operand is always evaluated, and all side effects are completed before the right operand is evaluated.
    (TOÁN TỬ ',': các biểu thức con được lượng giá theo thứ tự từ trái sang phải)

    Commas can be used as separators in some contexts, such as function argument lists. Do not confuse the use of the comma as a separator with its use as an operator; the two uses are completely different.
    (TOÁN TỬ ',' và dấu phân phân cách ',' là HOÀN TOÀN KHÁC NHAU)
    Như vậy dấu phẩy trong danh sách khởi tạo "Thing(int& r) : ref(r), MAX(100), arr (MAX) {}" không phải là operator (không quyết định thứ tự các thao tác) mà chỉ đơn thuần là 1 dấu phân cách

    Cám ơn bạn rox_rook đã chia xẻ (nhờ vậy tui học thêm 1 cái mới)

    (hiểu biết nông cạn có gì sai sót mong dược góp ý; xin cám ơn)

    -thân
    Đã được chỉnh sửa lần cuối bởi bete : 30-01-2008 lúc 03:25 AM.

  7. #7
    Ngày gia nhập
    07 2006
    Bài viết
    121

    Code:
    class Person{ 
    private: 
     int age; 
     string name; 
    public: 
     Person(int a, const string & n)  
     { 
     //chú ý chỗ này là phép gán chứ không phải khởi tạo.  
     age = a;  
     name = n;  
     } 
    };
    Tôi thấy code như thế này là đẹp rùi thân thiện nữa còn phép gán hay không thì cậu nên suy nghĩ lại cho thích hợp.
    Tôi thấy age = a đâu có sao còn name = n nếu cậu ngại thì chơi luôn như vậy
    name = new string(n);

    OoShinHaoO

  8. #8
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Đúng như anh nói, cái đó thực sự không sao, nhưng em nghĩ :
    PHP Code:
     age a;  
     
    name n
    chỗ này thực sự là implicit conversion nó được gọi, cái đúng khởi tạo phải là như anh làm ở trên. Vấn đề thực ra em chỉ muốn làm rõ vấn đề để hiểu rõ thêm thôi, vì nhiều khi sơ ý những lỗi không đáng có như thế debug cũng trần ai lắm ạ T_T. Anyways thanhks ý kiến của anh. Lâu rùi mới thấy anh quay lại diễn đàn nhỉ

Các đề tài tương tự

  1. Cách khai báo class trong tetris
    Gửi bởi trikhang2904 trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 0
    Bài viết cuối: 13-12-2013, 03:34 PM
  2. lỗi khai báo của class trong C++
    Gửi bởi boymafia1993 trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 13
    Bài viết cuối: 11-10-2012, 12:33 AM
  3. Kỹ thuật C++ Con trỏ hàm khai báo trong class như thế nào?
    Gửi bởi kukopuka trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 3
    Bài viết cuối: 30-03-2011, 05:02 PM
  4. Kỹ thuật C++ thắc mắc về khai báo hàm trong class
    Gửi bởi manocanh trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 1
    Bài viết cuối: 01-12-2010, 11:28 AM
  5. khai báo 1 class trong chương trình C++?
    Gửi bởi JackieWoo trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 10
    Bài viết cuối: 14-06-2010, 03:25 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn