我应该使用函数指针还是多态性

Should I use function pointers or polymorphism?

本文关键字:多态性 指针 函数 我应该      更新时间:2023-10-16

我需要将对象传递给类,并根据此传递对象中的值,使类使用两组方法之一。在这个类中,我不会以任何方式改变 b。我希望这对用户尽可能透明,以便他们传入对象,然后像往常一样调用方法,所以我试图避免将 Foo1 和 Foo2 类分开管理。

例如

class Foo
{
    public:
        Foo(Bar & b){
            useScheme1 = b.a == 1;
        }
        void methodA(){
            // call either A1 or A2
        }
        void methodB(){
            // call either B1 or B2
        }
    protected:
        bool useScheme1 = false;
        // methods A1, A2, B1 and B2 defined as protected functions
        .
        .
        .
};

这种功能正是动态多态性的用途!我绝对建议使用一个非常基本的创建器函数和Foo+孩子,如下所示:

namespace foo_library {
class Foo
{
public:
    virtual void methodA() = 0;
    virtual void methodB() = 0;
    virtual ~Foo() {}
};
class Foo1 : public Foo
{
    virtual void methodA()
    {
        // Do A1 here.
    }
    virtual void methodB()
    {
        // Do B1 here.
    }
};
class Foo2 : public Foo
{
    virtual void methodA()
    {
        // Do A2 here.
    }
    virtual void methodB()
    {
        // Do B2 here.
    }
};
Foo* create_foo(const Bar& b)
{
    if(b.a == 1) return new Foo1;
    return new Foo2;
}
}
// Then you use it like this:
int main()
{
    Bar b; // Initialize it.
    std::unique_ptr<foo_library::Foo> foo = foo_library::create_foo(b);    // Use the appropriate smart pointer for your ownership needs.
    foo->MethodA();   // Decides which to do based on the bar.
}

一般来说,使用函数指针来实现你正在尝试做的事情是问题的 C 解决方案。 你用C++而不是C编写代码。 所以这不言自明。

也就是说,在这里使用指针可以让您灵活地做出最后一刻的运行时决策,可能基于其他参数的值(例如,如果您需要选择要使用的函数,并且这些函数可能不是基于对象而是其他一些运行时条件(。

除了上面提到的场景之外,我会使用多态性;在我看来,它使代码更加透明。

这是C++11。 pImpl 类型擦除。

struct Foo {
  Foo( Bar const& b ):
    pScheme( makeScheme1(b.a==1) )
  {}
  void methodA() { pScheme->methodA(this); }
  void methodB() { pScheme->methodB(this); }
private:
  struct Scheme {
    virtual void methodA(Foo* self) const = 0;
    virtual void methodB(Foo* self) const = 0;
    virtual ~Scheme() {};
  };
  std::shared_ptr<const Scheme> pScheme;
  struct Scheme1:Scheme {
    void methodA(Foo* self) const override {
      std::cout << "Scheme1::methodA[" << self << "]n";
    }
    void methodB(Foo* self) const override {
      std::cout << "Scheme1::methodB[" << self << "]n";
    }
  };
  struct Scheme2:Scheme {
    void methodA(Foo* self) const override {
      std::cout << "Scheme2::methodA[0x" << self << "]n";
    }
    void methodB(Foo* self) const override {
      std::cout << "Scheme2::methodB[0x" << self << "]n";
    }
  };
  std::shared_ptr<const Scheme> makeScheme( bool bScheme1 ) {
    if (bScheme1) { return std::make_shared<Scheme1>(); }
    else { return std::make_shared<Scheme2>(); }
  }
};

现在你可以基于 Bar 构造一个Foo,它会根据 b 的参数构建一个内部Scheme

Scheme中,我传递了一个Foo* self,以便您可以访问Foo的数据,以备不时之需。

这里有继承,但这是客户端不关心的实现细节。 您的Foo就像值类型,而不是指针类型,这使得它更易于使用。 您甚至可以使用另一个Foo分配一个Foo,它就可以工作(源的方案是共享的(。

如果要支持Scheme -less Foo ,则需要在取消引用之前检查pScheme。 就目前而言,从Foo中移动是不安全的,可以调用methodAmethodB