Làm thế nào để đẩy dữ liệu ra một hàm xử lý nằm bên ngoài đối tượng trong C++

Hi Văn Dương.

  1. Lấy ví dụ thì chắc là bạn đã hiểu được nó.
  2. OOP không liên quan đến ngôn ngữ. 1 ngôn ngữ được chứng nhận hỗ trợ OOP thì có thể cài đặt được. //Bạn học OOP của C# như nào vậy hỏi thật ?
  3. Mình không hiểu ý bạn thất,

P/S Có lẽ mình cần xem lại phần OOP.

Đoạn này e thấy bác chưa khai thác triệt để chức năng của OOP rồi.

Tuy nhiên đoạn này e chưa hiểu rõ mục đích và code của bác nên chưa mường tượng được

1 Like

2, Ý mình là OOP thì nó đều có những tính chat giong nhau. Tức là OOP khi triển khai với C++, Java, C# là khá going nhau. Nên mình đã làm OOP C# khá nhiều thì mình có thể hiểu được một phần OOP trên C++ hay Java.
Mình tự học qua tài liệu nhiều nguồn, đã test và sử dụng cũng lâu rồi. Ý mình vậy thôi.

  1. Ý mình là như vậy, các bạn hay nghĩ that đơn giản. Mình lấy ví dụ từ C# qua
class MyClass{
    Button button = new Button();
    
    void CustomMethod(....){}

    MyClass(){
        button.Click+=CustomMethod;
    }
}

Tức là khi button nhấn, nó sẽ gọi hàm CustomMethod chạy trong khi hàm này nằm bên ngoài button đó mà MyClass và Button không có lien hệ gì với nhau cả. MyClass mình tự viết, Button thì đã được build ra dll trước đó rồi.

Bạn sẽ thấy code của Button là không thể sửa. Nó vẫn có thể truyền tham số gọi một hàm bất kỳ nằm trong class hay đối tượng bất kỳ chạy.

Quay lại C++, mình cũng muốn làm như vậy, có thể button sẽ được build thành lib và dll rồi. Khi click vào nó nó vẫn có thể gọi một hàm bất kỳ trong đối tượng bất kỳ chạy.

Mình muốn từ bên trong đối tượng A gọi một hàm nằm trong một đối tượng B chạy.

Các bác hình như đang nhầm là mình đang kế thừa với đa hình.
Thực chat là A,B là 2 đối tượng hoàn toàn không có quan hệ kế thừa mà là 2 đối tượng riêng rẽ hoàn toàn.
Mình sẽ làm thế nào để từ trong A gọi một hàm trong B chạy.

Thì xài std::bind đó thôi @@
Thằng bind này nó cần biết hàm đó do object nào giữ, sau đó gán thêm tham biến.

Deligate của C# nó mặc định các hàm gán vào là void rồi, các object giữ “Clicked”, … cũng luôn cố định tham biến là (object, event) => bác dựa vào đó rồi tạo theo là được thôi.

đừng xài std::bind. Nó chậm thê thảm lắm, ở trên bạn cũng đã nói là đừng nên xài rồi, nhắc lại làm gì, xài lambda hết @_@ C++ nghe tới “bind” là ghê tởm nhất, kế đó chắc là inheritance… :joy:

2 Likes

chưa bàn tới hiệu năng, muốn thoải mái thì cứ xài std::function. Muốn chơi kiểu button.Click+=CustomMethod; thì cứ phang 1 cái vector<function> là ngon lành

#include <iostream>
#include <vector>
#include <functional>
#include <string>

template<class... Args>
struct MyDelegate {
    using Function = std::function<void(Args...)>;
    std::vector<Function> functions;
    void operator+=(Function func) { functions.push_back(func); }
    void operator()(Args... args) { for (auto func : functions) func(args...); }
};

struct A {
    double d;
    explicit A(double d=0) : d{d} {}
    void operator()(int n, const std::string& s, char c)
    { std::cout << "A " << d << " " << n << " " << c << " " << s << "\n"; };
};

struct B {
    double d = 98.76;
    explicit B(double d=0) : d{d} {}
    void operator()(int n, const std::string& s)
    { std::cout << "Functor " << d << " " << n << " " << s << "\n"; };
};

void func(int n, const std::string& s)
{
    std::cout << "Function " << n << " " << s << "\n";
};

int main()
{
    MyDelegate<int, const std::string&> delegate;
    
    // thêm hàm bằng... hàm
    delegate += func;
    
    // thêm hàm bằng functor
    delegate += B{98.76};
    
    // thêm hàm bằng lambda
    delegate += [](int n, const std::string& s) { std::cout << "Lambda " << n << " " << s << "\n"; };
    
    // gọi hàm của a thông qua lambda
    A a{123.456};
    delegate += [&](int n, const std::string& s) { a(n, s, 'x'); };
    
    // tạo 1 object cho lambda chứa
    delegate += [a = A{11.22}](int n, const std::string& s) mutable { a(n, s, 'y'); };
    
    // gọi delegate
    delegate(11, "Hello");
}

/* kết quả
Function 11 Hello
Functor 98.76 11 Hello
Lambda 11 Hello
A 123.456 11 x Hello
A 11.22 11 y Hello
*/

còn nhiều cái nữa mới bằng C# delegate được, nhưng có tạm 2 cái operator+= và operator() là chạy tạm rồi

2 Likes

Mình nhớ lâu rồi có đọc trên SO họ bảo vẫn không thể thay thế hoàn toàn bind với lambdas trong một vài trường hợp :?

Edit: à đây nè, nhưng C++14 mới dứt hoàn toàn được.


5 Likes

tự hỏi tự trả lời rồi @_@

3 Likes

Cái này nhìn có vẻ dễ hiểu hơn std::bin :slight_smile:

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?