Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 策略模式或函数指针 在C++中,当我有一个可以接受不同行为的算法时,我使用函数指针。p>_Java_C++_Design Patterns_Function Pointers_Strategy Pattern - Fatal编程技术网

Java 策略模式或函数指针 在C++中,当我有一个可以接受不同行为的算法时,我使用函数指针。p>

Java 策略模式或函数指针 在C++中,当我有一个可以接受不同行为的算法时,我使用函数指针。p>,java,c++,design-patterns,function-pointers,strategy-pattern,Java,C++,Design Patterns,Function Pointers,Strategy Pattern,例如,一个绘制图表的程序有一个绘制线条的算法,该算法可以接受任何函数来专门化线条的形状 在Java中没有函数指针,我不得不使用策略模式或反射(或其他模式) 如何在程序运行时选择特殊行为? 策略模式Java函数指针中的函数指针?都是使用函子实现的。用一个函数创建一个接口,并传递它的实例,而不是函数指针。让你的C++代码看起来像: void func(void (*f)(int par)); 在Java中,这看起来像: public interface F { public void f(in

例如,一个绘制图表的程序有一个绘制线条的算法,该算法可以接受任何函数来专门化线条的形状

在Java中没有函数指针,我不得不使用策略模式或反射(或其他模式)

如何在程序运行时选择特殊行为?
策略模式Java函数指针中的函数指针?

都是使用函子实现的。用一个函数创建一个接口,并传递它的实例,而不是函数指针。让你的C++代码看起来像:

void func(void (*f)(int par));
在Java中,这看起来像:

public interface F {
  public void f(int par);
}

void func(F f);

看看番石榴的课程。这也是一个不错的C++方法。它更具可读性,并允许用户传递带有状态的对象,而不是静态函数。

这完全取决于您对函子所做的操作。如果要将其用作一次性操作,则需要使用模板。作为示例,请参见任何标准算法,例如:

您将使用以下选项:

int f(int i) { return 2*i; }

template <int I>
struct Constant {
    int operator()(int ) { return I; }
};

SaveFunctionForLater add1([](int i){return i+1;});    // works with lambda
SaveFunctionForLater double(f);                       // works with func ptr
SaveFunctionForLater zero(Constant<0>{});             // works with object

cout << add1.callMe(2);                  // prints 3
cout << double.callMe(double.callMe(4)); // prints 16
cout << zero.callMe(42);                 // prints 0
intf(inti){返回2*i;}
模板
结构常数{
int运算符()(int){return I;}
};
SaveFunctionForLater add1([](int i){return i+1;});//与lambda合作
SaveFunction for Later double(f);//与func ptr合作
SaveFunctionForLater零(常数{});//与对象一起工作

Cuth.P>在C++中有多种实现策略模式的方法。
  • 像在其他编程语言中一样使用OOP方法
  • 使用函数对象
  • 使用策略类
  • 三者都能完成任务,所以选择哪一个取决于你的问题

    您提到要使用策略来绘制图表。在我看来,这是一个复杂的用例,您应该选择选项一,因为您的策略对象可能会查询首选颜色等设置,您可能希望将策略存储在某个位置,以便用户可以在组合框中选择它们

    如果你想给客户(你的同事)很大的灵活性,函数对象真的很好。在我当前的项目中,我们在算法中使用函数对象进行停止标准测试。这对于C++11中的lambdas非常好,只要功能不变得太复杂

    基于策略的方法可能是最快的,但它需要在编译时知道类型。使用此插件时没有DLL基本插件。至少在将实现封装到类层次结构中之前:

    模板
    类MyClass
    {
    空做某事
    {
    LockPolicy::lock();
    //...
    LockPolicy::unlock();
    }
    };
    
    我认为好的建议是:

    • 使用1。如果策略复杂,可能会询问其他系统
    • 使用1。如果您希望通过插件实现新的战略
    • 使用2。如果策略可以用短代码行表示
    • 使用2。如果策略实现适合自由函数,并且您不想引入类层次结构
    • 使用3。如果你真的知道自己在做什么,你需要表演

    实施什么“操作”?你认为什么是“最好”(这是一个非常主观的词)?您的用例是什么?我指的是允许在运行时选择算法行为的操作。c++11?参见lambdas和
    std::function
    使用它而不是策略模式是否是一个好的规则?我不知道哪一个更好。这几乎就是战略模式。F是您的策略接口,它的子类是实际的策略。@BenjyKessler Link Brokernok,谢谢。我想在我的程序中存储用于绘制图表的函数,因此在这种情况下,使用指针不是一个好主意?@ElConrado您可以存储函数指针,但只能存储到实际函数(无论是自由函数还是静态函数)。但是如果使用
    std::function
    ,则可以使用任何可调用函数。那会使你的课更有用。
    class SaveFunctionForLater {
    public:
        template <typename F>
        SaveFunctionForLater(F&& f)
            : func(std::forward<F>(f))
            { }
    
        int callMe(int i) { return func(i); }
                                   ^^^^
                                   use the saved one
    
    private:
        std::function<int(int)> func; // function taking an int, returning an int
    };
    
    int f(int i) { return 2*i; }
    
    template <int I>
    struct Constant {
        int operator()(int ) { return I; }
    };
    
    SaveFunctionForLater add1([](int i){return i+1;});    // works with lambda
    SaveFunctionForLater double(f);                       // works with func ptr
    SaveFunctionForLater zero(Constant<0>{});             // works with object
    
    cout << add1.callMe(2);                  // prints 3
    cout << double.callMe(double.callMe(4)); // prints 16
    cout << zero.callMe(42);                 // prints 0