【问题标题】:Call derived class function from parent class without knowing derived class在不知道派生类的情况下从父类调用派生类函数
【发布时间】:2015-03-12 20:35:37
【问题描述】:

我正在尝试构建一个带有父类的软件,该父类调用派生类函数而不知道派生类本身。我一直在考虑它,但没有找到真正的解决方案。我想我应该从派生类中获取一个指针,以便使用父类执行代码。

这是我想要实现的目标:

我有一个带有纯虚函数的父类。派生类将实现所述功能。父类也将有一个静态函数,其中(使用向量)将执行派生类函数的代码。

class Base {

    static std::vector<Base*> vec;

public:

    virtual void Test() = 0;
    static void Func();
};

class Derived : public Base {
public:
    void Test()
    {
        std::cout<<"hello";
    }
};

void Base::Func()
{
    for (int i = 0; i != vec.size(), i++)
    {
        vec[i]->Test();
    }
}

问题是:我需要从每个派生类中调用“Test()”函数。但这必须以编程方式完成,因为我不知道会创建哪些其他派生类

示例:

//Base.h
class Base {

        static std::vector<Base*> vec;

    public:

        virtual void Test() = 0;
        static void Func();
};


//Base.cpp
void Base::Func()
{
    for (int i = 0; i != vec.size(), i++)
    {
        vec[i]->Test();
    }
}

我的 Base::Func() 将在任何帧被调用。

此时“用户”将创建自己的实现和头文件,如下所示:

//Derived.h
class Derived : public Base {
public:
    void Test() override;
};

//Derived.cpp

void Derived::Test() 
{
    //Insert code here
}

提前感谢您的帮助。

PS 我需要类似游戏引擎的更新方法的东西。就像 cocos2d 的更新方法一样。

【问题讨论】:

  • 有什么问题吗? (这应该就像你描述的那样工作)
  • 问题是:我需要从每个派生类中调用“Test()”函数。但这必须以编程方式完成,因为我不知道将创建哪些其他派生类
  • 您的解决方案非常完美。这正是虚拟的目的。你试过了吗?
  • 由于您需要创建一个对象来存储所有派生对象,只需将Func() 设为非静态并从包含所有派生类的对象中调用它。
  • 如果您尝试发布的代码,您究竟会在哪里停止?

标签: c++ class inheritance


【解决方案1】:

这似乎是 CRTP(奇怪地重复出现的模板模式)的一个用例。假设我们有一个在 T 类型下模板化的基础

template<typename T>
struct Base
{
    void Fun()
    {
        ((T*)this)->Fun(); 
    }
}

您在这里所做的是将this 对象转换为T 类型并调用该类型的相应函数。这有什么帮助?想象一下从那个类继承,只有你在你的类型下模板化它(是的,这是合法的)

struct Derived : Base<Derived>
{
    void Fun(); 
}

这样你就可以“在不知道派生类的情况下从父类调用派生类函数”,前提是派生类实现了基类“预测”的接口。例如,如果有人定义了一个新类Derived2,您可以编写这样的代码

Base<Derived2> obj; 
obj.Fun(); // calls Fun of the derived object

【讨论】:

  • 感谢您的回答,但我是不是错了,或者如果不创建对象就无法工作?
  • @user3772833 确实如此。它是类型的属性。当然,调度将在运行时处理,但类型特征查询按预期工作
  • 你能给我看一个不创建对象的例子吗?谢谢
  • 所有这一切都会调用未定义的行为。
  • @5gon12eder CRTP 是什么?
【解决方案2】:

如果您需要派生一个类来实现该功能,那么没有对象就无法按照您想要的方式调用它。但是,使用它们的向量,就像您的代码一样,这很容易:

#include <iostream>
#include <vector>

using namespace std;

namespace game{

class base{
  void add_to_vec(base* b);
  public:
  base(){add_to_vec(this);}
  virtual void test()=0;
  static void testAll();
};

static vector<base*> vec;

void base::add_to_vec(base* b){vec.push_back(b);}

void base::testAll()
{
  for (int i = 0; i != vec.size(); i++)
  {
    vec[i]->test();
  }
}

}

class derived1 : public game::base{
  public:
  void test() {cout << "Derived 1" << endl;}
};

class derived2 : public game::base{
  public:
  void test() {cout << "Derived 2" << endl;}
};

int main(){
  derived1 a;
  derived2 b;
  game::base::testAll();
}

为简单起见,我省略了从向量中删除对象的代码,你也应该很容易理解。

【讨论】:

  • 谢谢你,就像我会做的那样。我仍然想知道像 Cocos2d 这样的游戏引擎如何在不创建对象的情况下调用更新函数,这是我想要实现的,我一直在努力解决这个问题,因为我找不到任何解决方案涉及正在创建的对象
猜你喜欢
  • 1970-01-01
  • 2020-02-25
  • 1970-01-01
  • 2011-01-21
  • 2011-06-19
  • 2014-01-01
  • 1970-01-01
相关资源
最近更新 更多