虚拟重载vs`std :: function`成员?

Lev*_*ans 5 c++ c++11

我正处于一个班级,让我们称之为班级Generic.这个类有成员和属性,我打算在一个std::vector<Generic>或类似的地方使用它,处理这个类的几个实例.

此外,我想专门化这个类,泛型和专用对象之间的唯一区别是私有方法,它不访问类的任何成员(但由其他方法调用).我的第一个想法是简单地声明它virtual并在专门的类中重载它,如下所示:

class Generic
{
    // all other members and attributes
    private:
        virtual float specialFunc(float x) const =0;
};

class Specialized_one : public Generic
{
    private:
        virtual float specialFunc(float x) const{ return x;}
};

class Specialized_two : public Generic
{
    private:
        virtual float specialFunc(float x) const{ return 2*x; }
}
Run Code Online (Sandbox Code Playgroud)

因此我想我必须使用a std::vector<Generic*>,并动态创建和销毁对象.

一位朋友建议我std::function<>为我的Generic类使用一个属性,并将其specialFunc作为参数提供给构造函数,但我不确定如何正确地执行它.

这两种方法的优点和缺点是什么,还有其他(更好的)方法来做同样的事情吗?我很好奇.

有关详细信息,我实例化的每个对象的特化将在运行时确定,具体取决于用户输入.我可能最终会得到很多这些对象(还不确定有多少),所以我想避免任何不必要的开销.

Dan*_*vil 5

virtual函数和重载模型是一种关系,而std::function模型是一种关系.

使用哪一个取决于您的具体用例.

使用std::function可能更灵活,因为您可以轻松修改功能而无需引入新类型.


性能不应该是这里的主要决策点,除非这个代码可以证明(即你测量过)程序中的紧密循环瓶颈.


Moh*_*oun 3

首先,让我们把性能抛到九霄云外。

如果您使用virtual函数,正如您所说,您最终可能会得到许多具有相同接口的类:

class generic {
    virtual f(float x);
};

class spec1 : public generic {
    virtual f(float x);
};

class spec2 : public generic {
    virtual f(float x);
};
Run Code Online (Sandbox Code Playgroud)

作为会员使用std::function<void(float)>可以让您避免所有专业化:

class meaningful_class_name {
    std::function<void(float)> f;

public:
    meaningful_class_name(std::function<void(float)> const& p_f) : f(p_f) {}
};
Run Code Online (Sandbox Code Playgroud)

事实上,如果这是您使用该类的唯一用途,您不妨删除它,并std::function<void(float)>在调用者级别使用 a 。

优点std::function

1)更少的代码(N个函数需要1个类,而虚拟方法需要N个函数的N个类。我假设这个函数是类之间唯一不同的东西)。
2) 更加灵活(如果需要,您可以传入捕获保存状态的 lambda)。
3)如果将类编写为模板,则可以根据需要将其用于各种函数签名。

使用std::function可以解决您尝试使用virtual函数解决的任何问题,而且它似乎做得更好。但是,我不会断言这std::function总是比几个类中一堆虚拟函数更好。有时,这些函数必须是私有的和虚拟的,因为它们的实现与任何外部调用者无关,因此灵活性并不是一个优势。

缺点std::function

1)我正要写你不能访问类的私有成员generic,但后来我意识到你可以使用std::function捕获 lambda 来修改类本身中的this。然而,考虑到您概述该类的方式,这应该不是问题,因为它似乎忽略了任何类型的内部状态。