c++仅为特定实例重写函数

c++ overriding a function only for a specific instance

本文关键字:实例 重写 函数 c++      更新时间:2023-10-16

我想知道是否有一种方法可以只覆盖特定实例的函数。例如

class A
{
public:
    ...
    void update();
    ...
}
int main()
{
    ...
    A *first_instance = new A();
    // I want this to have a specific update() function.
    // ex. void update() { functionA(); functionB(); ... }
    A *second_instance = new A();
    // I want this to have a different update() function than the above one.
    // ex. void update() { functionZ(); functionY(); ...}
    A *third_instance = new A();
    // ....so on.
    ...
}

有办法做到这一点吗?

我认为虚拟函数正是你想要的,有了虚拟函数,同一类型的不同实例可以有不同的函数,但你需要继承基类。例如

class A
{
    public:
        ...
        virtual void update()
        {
            std::cout << "Class An";
        }
        ...
};
class B: public A
{
    public:
        virtual void update()
        {
            std::cout << "Class Bn";
        }
};
class C: public A
{
    public:
        virtual void update()
        {
            std::cout << "Class Cn";
        }            
};
int main()
{
    ...
    A *first_instance = new A();
    // I want this to have a specific update() function.
    // ex. void update() { functionA(); functionB(); ... }
    A *second_instance = new B();
    // I want this to have a different update() function than the above one.
    // ex. void update() { functionZ(); functionY(); ...}
    A *third_instance = new C();
    // ....so on.
    ...
}

上面代码中的每个实例都将绑定不同的更新函数。

此外,您也可以使用函数指针来实现您的需求,但不建议这样做。例如

class A
{
    public:
        A(void(*u)())
        {
            this->update = u;
        }
        ...
        void (*update)();
};
void a_update()
{
    std::cout << "update An";
}
void b_update()
{
    std::cout << "update Bn";
}
void c_update()
{
    std::cout << "update Cn";
}
int main()
{
    ...
    A first_instance(a_update);
    // I want this to have a specific update() function.
    // ex. void update() { functionA(); functionB(); ... }
    A second_instance(b_update);
    // I want this to have a different update() function than the above one.
    // ex. void update() { functionZ(); functionY(); ...}
    A third_instance(c_update);
    // ....so on.
    ...
}

希望有帮助!

在类中保持一个function

#include <iostream>
#include <functional>
using namespace std;
class Foo
{
public:
    Foo(const function<void ()>& f) : func(f)
    {
    }
    void callFunc()
    {
        func();
    }
private:
    function<void ()> func;
};
void printFoo() { cout<<"foo"<<endl; }
void printBar() { cout<<"bar"<<endl; }
int main()
{
    Foo a(printFoo);
    Foo b(printBar);
    a.callFunc();
    b.callFunc();
}

您可能已经注意到,类的右大括号后面通常跟有分号,而函数、while循环等的右大引号后面则没有。这是有原因的,这与C中struct的一个特性有关。因为class几乎与struct相同,所以C++类也存在这个特性。

基本上,C中的struct可以声明一个命名实例,而不是(或)一个命名的"类型"(因为C中的struct类型本身不是有效的类型名,所以使用引号)。因此,C++类可以做同样的事情,尽管AFAIK可能对该类的其他功能有严重的限制

我现在无法检查,当然我也不记得使用过它,但这可能意味着你可以声明一个从基类继承的命名类实例,而不给它一个类名。仍然会有一个派生类型,但它将是匿名的。

如果有效,它应该看起来像。。。

class : public baseclass  //  note - no derived class name
{
  public:
    virtual funcname ()
    {
      ...
    }
} instancename;

就我个人而言,即使这是有效的,我也会避免使用它,原因有很多。例如,缺少类名意味着不可能单独定义成员函数。这意味着整个类的声明和定义必须放在你想要声明实例的地方——在函数的中间,甚至在全局变量的列表中,会有很多混乱。

如果没有类名,可能就没有办法声明构造函数或析构函数。如果你有来自基类的非默认构造函数,那么AFAIK就没有办法用它来指定构造函数参数。

正如我所说,我还没有检查过这一点——这种语法很可能是非法的,也很丑陋。

针对每个实例的不同行为,一些更实用的方法包括。。。

  1. 使用依赖项注入-例如,为行为的某个部分提供函数指针或类实例(或lambda)作为构造函数参数。

  2. 使用模板类有效地编译时依赖项注入,依赖项作为模板的函数参数提供。

我认为最好告诉我们为什么需要为特定实例重写函数
但这里有另一种方法:战略模式

你的班级需要一个能代表某些行为的成员。因此,您正在创建一些抽象类,它将成为不同行为的接口,然后您将在该抽象类的子类中实现不同的行为。因此,您可以在任何时间为任何对象选择这些行为。

class A;//forward declaration
class Updater
{
public:
    virtual ~Updater() {};//don't forget about virtual destructor, though it's not needed in this case of class containing only one function
    virtual void update(A&) = 0;
}
class SomeUpdater
{
public:
    virtual void update(A & a);//concrete realisation of an update() method
}
class A
{
private:
    Updater mUpdater;
public:
    explicit A(Updater updater);//constructor takes an updater, let's pretend we want to choose a behaviour once for a lifetime of an object - at creation
    void update()
    {
        mUpdater.update(this);
    }
}

您可以使用本地类,但就我个人而言,我认为另一个答案中提到的"类中保持函数"方法更好。只有当doFunc必须访问基类的内部时,我才建议使用以下方法,这在成员变量中的函数中是不可能的:

class ABase {
public:
    void Func () { this->doFunc (); }
private:
    virtual void doFunc () = 0;
public:
    virtual ~ABase () { }
};
ABase* makeFirstA () {
    class MyA : public ABase {
        virtual void doFunc () { std::cout << "First A"; }
    };
    return new MyA;
}
ABase* makeSecondA () {
    class MyA : public ABase {
        virtual void doFunc () { std::cout << "Second A"; }
    };
    return new MyA;
}
int main () {
    std::shared_ptr<ABase> first (makeFirstA ());
    std::shared_ptr<ABase> second (makeSecondA ());
    first->Func ();
    second->Func ();
}

从设计模式的角度来看,"局部类"方法实现了模板方法模式,而"在成员变量中保持函数(al)"方法则反映了<em]策略模式>