1

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

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.
    ...
}

有没有办法做到这一点?

4

5 回答 5

10

我觉得虚函数正是你想要的,有了虚函数,同类型的不同实例可以有不同的功能,但是你需要继承基类。例如

class A
{
    public:
        ...
        virtual void update()
        {
            std::cout << "Class A\n";
        }
        ...
};

class B: public A
{
    public:
        virtual void update()
        {
            std::cout << "Class B\n";
        }
};

class C: public A
{
    public:
        virtual void update()
        {
            std::cout << "Class C\n";
        }            

};

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 A\n";
}

void b_update()
{
    std::cout << "update B\n";
}

void c_update()
{
    std::cout << "update C\n";
}

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.
    ...
}

希望有所帮助!

于 2013-08-11T10:46:11.347 回答
5

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();
}
于 2013-08-11T10:59:03.657 回答
2

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

基本上,structC 中的 a 可以声明一个命名实例,而不是(或以及)一个命名的“类型”(因为structC 中的类型本身不是有效的类型名称,所以用引号引起来)。因此,C++ 类可以做同样的事情,尽管 AFAIK 可能对该类可以做的其他事情有严格的限制。

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

如果完全有效,它应该看起来像......

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

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

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

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

一些更实用的方法来改变每个实例的行为包括......

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

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

于 2013-08-11T11:36:56.043 回答
1

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

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

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);
    }
}
于 2013-08-13T16:05:29.840 回答
0

您可以使用本地类,但就个人而言,我认为另一个答案中提到的“类中的保留函数”方法更好。仅当必须访问基类的内部时,我才建议使用以下方法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 ();
}

从设计模式的角度来看,“本地类”方法实现了模板方法模式,而“在成员变量中保存函数”方法反映了策略模式。哪个更合适取决于您需要实现的目标。

于 2013-08-11T11:13:04.967 回答