【问题标题】:How to make abstraction for Base class using virtual functions?如何使用虚函数对基类进行抽象?
【发布时间】:2011-09-08 08:37:36
【问题描述】:

我有以下结构

class Base
{
public:
    Base(Type);
    virtual render
}

class A
{
public:
    Base(Type == A);
    void render()
}

class B
{
public:
    Base(Type == B);
    void render()
}

void client_function()
{
    Base baseObject(A);
    //Base is an instance of class A
    baseObject.render()//runs class A render
}

据我所知,上述代码中有些东西不是 c++,它们与 Haskell 中的模式匹配密切相关,但这是我能找到的最好的方式来说明我的问题,而无需知道答案;)

在写作中我希望客户端能够创建一个基础对象并将对象的类型作为参数传递,返回对象的正确规范并且客户端不需要关心它,只知道运行渲染将运行正确的特定渲染。

如果我不清楚,请随时提出问题:)

【问题讨论】:

  • 您可能想从一本基本的 C++ 书籍或教程开始,似乎您缺少一些基本的继承概念和所有其他面向对象的概念。如果您想要的东西不属于该类别,您可能正在查看 CRTP(静态多态性),但在没有更深入了解确切问题的情况下决定其中一个是不可能的。

标签: c++ inheritance virtual-functions


【解决方案1】:
【解决方案2】:

您需要运行时多态性。构造函数没有太多重要的部分。您必须将Base 继承到AB。例如:

class Base
{
public:
  virtual void render ();  // <--- declare 'virtual'
  virtual ~Base();  // <--- very much needed to avoid undefined behavior
};
class A : public Base //<---- inheritance
{
public:
  void render();  // <--- this also becomes 'virtual'
};
...

现在您可以根据需要使用。

Base *baseObject = new A();  // <----- need to use pointer (or reference)
(*baseObject).render();  // <--- other way to write: baseObject->render();
delete baseObject;

【讨论】:

  • (*baseObject).render(); 也可以写成baseObject-&gt;render();(如果我的记忆没有出卖我的话)
  • A 类错字? (空虚)
  • @duedlOr,真的是个不错的选择。虽然我打算给出最小的例子,但这是关键点(OP 绝不能错过)。
【解决方案3】:

我不确定我是否理解您的问题。在 C++ 中,你不能在运行时选择你的基类,但你当然可以让你的基类依赖于派生类。这是通过使用模板和所谓的Curiously Recurring Template Pattern 来完成的:

template <typename T> class Base {
public:
    virtual void render(T *) {}
};

class A : public Base<A>
{
public:
    void render(A * t) {}
};

class B : public Base<B>
{
public:
    void render(B * t) {}
};

void client_function() {
    A a1;
    A a2;
    a1.render(&a2); // calls A::render
    a1.Base<A>::render(&a2); // calls Base<A>::render
    Base<A> * ba = &a1;
    ba->render(&a2); // calls A::render
}

希望这能回答你的问题。

【讨论】:

    【解决方案4】:

    您所要求的正是继承的目的:从专门化功能的类层次结构中创建对象。

    在您的示例中,除了语法问题外,一切都会按您的预期进行,即方法 A::render 将被调用,即使您在编译时不知道该对象,声明为 Base,确实是A。这就是虚拟继承的魔力。

    【讨论】:

      猜你喜欢
      • 2013-06-29
      • 2019-04-20
      • 2020-07-01
      • 1970-01-01
      • 2011-03-21
      • 2023-03-14
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      相关资源
      最近更新 更多