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

Đề tài: Truyền class A vào hàm thành viên của class B?

  1. #1
    Ngày gia nhập
    12 2009
    Bài viết
    28

    Mặc định Truyền class A vào hàm thành viên của class B?

    Giả sủ mình có đoạn code như vầy.
    Code:
    class A
    {
    	int a;
    public:
    	A(int);
    };
    
    class B
    {
    	int b;
    public:
    	B(int);
    	void func(A& _classA)
    	{
    		b = _classA.a; // Nó báo lỗi ko truy cập đc đến thành phần private
    	}
    };
    Vậy có cách nào làm đc mà ko dùng public cho int a hay 1 phuơng thức trog class A để get biến a không?

  2. #2
    Ngày gia nhập
    07 2011
    Bài viết
    160

    Trích dẫn Nguyên bản được gửi bởi alkill Xem bài viết
    Giả sủ mình có đoạn code như vầy.

    class B
    {
    int b;
    public:
    B(int);
    void func(A& _classA)
    {
    b = _classA.a; // Nó báo lỗi ko truy cập đc đến thành phần private
    }
    };
    [/CODE]

    Vậy có cách nào làm đc mà ko dùng public cho int a hay 1 phuơng thức trog class A để get biến a không?
    Bạn chọn 1 trong 2 cách sau:
    1. Viết hàm getter cho A::a (recommended) và truy cập qua hàm getter thay vì truy cập trực tiếp biến
    Code:
    class A
    {
    	int a;
    public:
    	A(int);
            int get_a() const {return a;}
    };
    2. Khai báo class B là friend của A:
    Code:
    class A
    {
    	int a;
    public:
    	A(int);
            friend class B;
    };
    Ngoài lề: nếu trong B::func chỉ đọc dữ liệu của A (chứ không thay đổi) thì nên viết:
    Code:
    void func(const A& _classA);
    hoặc cách viết khác:
    Code:
    void func(A const& _classA);
    const-correctness rất quan trọng và nên lưu ý từ đầu

    Edit: Chưa đọc kỹ, bạn nói không muốn dùng hàm getter. Mình không hiểu sao bạn không muốn dùng cái này? Nếu không được thay đổi declaration của A thì không có cách nào cả. Truy cập theo địa chỉ memory dù có thể được nhưng ra kết quả không ổn định trên các compiler khác nhau / các chế độ align khác nhau ==> rất mạo hiểm.
    Đã được chỉnh sửa lần cuối bởi fbchicken : 21-07-2011 lúc 09:44 PM.

  3. #3
    Ngày gia nhập
    11 2010
    Bài viết
    41

    Còn 1 cách nữa!

    đó là để hàm thành viên của lớp B là hàm bạn của lớp A.
    i dont care who are u, where yr from, what u did , as long as u love me

  4. #4
    Ngày gia nhập
    12 2009
    Bài viết
    28

    Cám ơn bạn nhiều.

    Ah. Tại mình thấy nếu dùng hàm getter vậy thì thà mình public nó cho rồi ). Bạn nghĩ sao??
    Đã được chỉnh sửa lần cuối bởi alkill : 21-07-2011 lúc 09:59 PM.

  5. #5
    Ngày gia nhập
    12 2009
    Bài viết
    28

    Trích dẫn Nguyên bản được gửi bởi vantrong Xem bài viết
    Còn 1 cách nữa!

    đó là để hàm thành viên của lớp B là hàm bạn của lớp A.
    Bạn nói rõ hơn đi.
    Mình thử là:
    Code:
    friend void B::func(const A&);
    trong lớp B mà ko đc.

  6. #6
    Ngày gia nhập
    07 2011
    Bài viết
    160

    Mặc định Truyền class A vào hàm thành viên của class B?

    Trích dẫn Nguyên bản được gửi bởi alkill Xem bài viết
    Cám ơn bạn nhiều.

    Ah. Tại mình thấy nếu dùng hàm getter vậy thì thà mình public nó cho rồi ). Bạn nghĩ sao??
    Getter không có hại gì cả. Public thì các class khác có thể thay đổi được biến đó, còn getter thì chỉ đọc được thôi và thường là vô hại. Thiết kế private member + public getter là thiết kế chuẩn và được dùng rất rất thường xuyên
    Nếu mà phải làm cả getter và setter (và chỉ đọc biến / gán biến) thì đúng là public cho rồi thật


    Còn về friend function thì viết như bạn là đúng rồi, nhưng bạn cũng phải khai báo trong class A. Cái này ít dùng vì:
    1. Thường thì người ta friend luôn cả class B cho gọn, đằng nào cũng là trong 1 module của mình nên việc friend function này mà che giấu với các function khác ít khi có ý nghĩa.
    2. Chỉ friend được các public function của B (protected/private thì B cũng phải friend class A mới được)
    Thế nên bình thường chỉ hay gặp friend cả class và friend global function, ít khi thấy friend member function của class khác

  7. #7
    Ngày gia nhập
    11 2010
    Bài viết
    41

    Trích dẫn Nguyên bản được gửi bởi alkill Xem bài viết
    Bạn nói rõ hơn đi.
    Mình thử là:
    Code:
    friend void B::func(const A&);
    trong lớp B mà ko đc.
    Cái này chắc là lỗi : "không biết hàm B::func() ở đâu phải ko. Cái này bạn phải khai báo lớp B ở trước lớp A nữa.
    C++ Code:
    1. class B;
    2. class A
    3. {
    4. friend void B::func();
    5. //...
    6. };
    7. class B
    8. {
    9. //...
    10. };

    Người ta thiết kế setter với mục đích kiểm soát việc gán giá trị cho biến thành viên. Còn dùng getter là tuân theo tính che dấu dữ liệu của OOP thôi mà

    Trích dẫn Nguyên bản được gửi bởi fbchicken Xem bài viết
    Cái này ít dùng vì:
    1. Thường thì người ta friend luôn cả class B cho gọn, đằng nào cũng là trong 1 module của mình nên việc friend function này mà che giấu với các function khác ít khi có ý nghĩa.
    Gọn, nhưng tùy mục đích mà sủ dụng chứ. Vì nhìu khi ta chỉ muốn cho 1 hoặc 1 số hàm thành viên của lớp B là friend của A mà không muốn cho tất cả các hàm thành viên còn lại.
    Đã được chỉnh sửa lần cuối bởi vantrong : 22-07-2011 lúc 05:29 PM.
    i dont care who are u, where yr from, what u did , as long as u love me

  8. #8
    Ngày gia nhập
    12 2009
    Bài viết
    28

    Mình viết như thế này nè:
    C++ Code:
    1. class B;
    2. class A
    3. {
    4.     int a;
    5. public:
    6.     A(int _a);
    7.     friend void B::func(const A&);
    8. };
    9.  
    10. class B
    11. {
    12.     int b;
    13. public:
    14.     B(int _b);
    15.     void func(const A&);
    16. };
    17. void B::func(const A& _classA)
    18. {
    19.     b = _classA.a; // Lỗi error C2248: 'A::a' : cannot access private member declared in class 'A'
    20. }
    nhưng vẫn lỗi

  9. #9
    Ngày gia nhập
    11 2010
    Bài viết
    41

    Trích dẫn Nguyên bản được gửi bởi alkill Xem bài viết
    Mình viết như thế này nè:
    C++ Code:
    1. class B;
    2. class A
    3. {
    4.     int a;
    5. public:
    6.     A(int _a);
    7.     friend void B::func(const A&);
    8. };
    9.  
    10. class B
    11. {
    12.     int b;
    13. public:
    14.     B(int _b);
    15.     void func(const A&);
    16. };
    17. void B::func(const A& _classA)
    18. {
    19.     b = _classA.a; // Lỗi error C2248: 'A::a' : cannot access private member declared in class 'A'
    20. }
    nhưng vẫn lỗi
    Ý chết ở trên mình viết lộn rồi.
    phải viết như sau

    C++ Code:
    1. class A;
    2.  
    3. class B  
    4. {
    5. void func(const A &_classA);
    6. };
    7. class A  
    8. {
    9. //...
    10. friend void B::func(const A &_classA);
    11. };
    12.  
    13. void B::func(const A &_classA)
    14. {
    15.  
    16. }

    thì mới đug':
    Đã được chỉnh sửa lần cuối bởi vantrong : 22-07-2011 lúc 08:41 PM.
    i dont care who are u, where yr from, what u did , as long as u love me

  10. #10
    Ngày gia nhập
    07 2011
    Bài viết
    160

    Trích dẫn Nguyên bản được gửi bởi vantrong Xem bài viết
    Gọn, nhưng tùy mục đích mà sủ dụng chứ. Vì nhìu khi ta chỉ muốn cho 1 hoặc 1 số hàm thành viên của lớp B là friend của A mà không muốn cho tất cả các hàm thành viên còn lại.
    Đương nhiên là tùy mục đích. Nhưng như mình đã nói, việc friend 1 member function rất ít khi có ý nghĩa.

    C++ càng ngày càng đưa ra nhiều thứ để người lập trình tự giới hạn mình, nhằm tránh những sai lầm do vô ý sinh ra. Có những thứ rất có ích và được mọi người nhanh chóng tiếp thu (ví dụ const-correctness). Cũng có những thứ đã được ồ ạt đưa vào các giáo trình Tây lẫn ta, và 1 thế hệ ngắn ngủi ồ ạt áp dụng, nhưng dần dần bị thải loại. Dù nó vẫn nằm trong chuẩn nhưng người ta không dùng nữa. Vì nó phiền phức, rắc rối mà không có nhiều tác dụng. Lấy ví dụ như khai báo throw của 1 function: Ý tưởng là 1 function nên khai báo nó có thể throw những exception gì.
    void ff() throw(); ==> function ff sẽ không throw bất kỳ 1 exception nào.

    Cái kiểu khai báo này vẫn tồn tại trong các thư viện chuẩn, kể cả trong STL đi kèm gnu c++ compiler. Nhưng hiện tại viết code hầu như không ai khai báo throw cho function nữa. Các sách mới ra cũng né tránh vấn đề này hoặc trực tiếp nói là không nên khai báo throw cho function

    Cơ chế public/protected/private cũng là 1 cơ chế để tự giới hạn mình/giới hạn người cùng code với mình hoặc sử dụng code của mình, và rất có ích. Tuy nhiên việc friend 1 member function của 1 class khác thì ít khi có ý nghĩa đến nỗi bạn hầu như chẳng bao giờ gặp. Bạn thử nghĩ xem lúc nào thì mình sẽ cần cho phép 1 function của class B truy cập mà phải che giấu với các function khác của class B? Thường khi bạn friend class B có nghĩa là class B cũng do chính bạn hoặc 1 người có hợp tác chặt chẽ với bạn viết. Và trong thiết kế tốt, 1 class là 1 đơn vị module hóa đủ nhỏ để thường chỉ có 1 người viết 1 class. Tất nhiên cũng có 1 số trường hợp ngoại lệ, ví dụ như việc truy cập biến khá phức tạp rắc rối dễ sinh lỗi, bạn sợ sau này bạn sẽ quên mất điều đó và truy cập bừa bãi. Trường hợp này có thể giải quyết bằng hệ thống document / comment tốt, cũng giống như hệ thống khai báo throw cho function đã được chuyển sang ghi bằng comment

    Bạn thử mở 1 code bất kỳ và so sánh tỷ lệ gặp friend 1 member function so với friend cả class / friend global function xem. Thường là tỷ lệ đó rất nhỏ. Và bạn đã mấy lần sử dụng friend member function trong code của bạn?

    Ý kiến mình vẫn là: trong > 95% (thậm chí 99.9%) số trường hợp, thay vì friend member function, bạn friend cả class cho đỡ mệt đầu. Chính bạn cũng thấy để khai báo friend 1 member function khá rắc rối, 1 người có kinh nghiệm như bạn mà cũng lẫn. Chưa kể như mình nói, nó có hạn chế là chỉ friend được public function, mà thường private function mới cần sử dụng nhiều hơn. Nhớ nó chỉ tổ tràn memory của nơ ron não

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

  1. Lỗi ko thể truyền dữ liệu giữa Class và Form thông qua Properties
    Gửi bởi hikagu2000 trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 1
    Bài viết cuối: 04-02-2012, 03:23 PM
  2. Lỗi không truyền được đối tượng khi tách file class
    Gửi bởi hoanghai27 trong diễn đàn Nhập môn lập trình C/C++
    Trả lời: 0
    Bài viết cuối: 25-03-2011, 01:20 AM
  3. ADO.NET Truyền dữ liệu gua lại giữa 2 form thông qua properties class
    Gửi bởi teodainhan trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 5
    Bài viết cuối: 05-01-2011, 04:34 PM
  4. Truyền chuỗi từ 1 form tới 1 class
    Gửi bởi minhduc0912 trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 10
    Bài viết cuối: 26-08-2009, 10:39 PM
  5. Truyền Dữ liệu giữa các Class ???
    Gửi bởi nam_dkn trong diễn đàn Thắc mắc lập trình Visual C++
    Trả lời: 4
    Bài viết cuối: 06-01-2009, 04:40 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