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

时间:2013-08-11 10:39:55

标签: c++ oop

我想知道是否有办法仅覆盖特定实例的函数。例如,

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

有没有办法实现这个目标?

5 个答案:

答案 0 :(得分:9)

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

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.
    ...
}
希望有所帮助!

答案 1 :(得分: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();
}

答案 2 :(得分:2)

您可能已经注意到类的结束括号通常后跟分号,而函数的末括号,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. 使用模板类 - 有效地编译时依赖项注入,并将依赖项作为函数参数提供给模板。

答案 3 :(得分:1)

我认为如果您告诉我们为什么需要覆盖特定实例的功能,那将是最好的。
但这是另一种方法:Strategy pattern

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

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);
    }
}

答案 4 :(得分: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 ();
}

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