使用基类中的函数静态调用纯虚函数的派生类实现

Posted

技术标签:

【中文标题】使用基类中的函数静态调用纯虚函数的派生类实现【英文标题】:Calling a derived-class implementation of a pure virtual function statically using a function in the base class 【发布时间】:2014-05-02 15:11:29 【问题描述】:

在***的其他地方有一些关于这个话题的讨论,但我还没有真正找到我的问题的明确答案。

我的设置是这样的:

class BaseClass

    virtual short return_number_for_thing1(std::string thing1)=0; //note the pure virtual
    virtual short return_number_for_thing2(std::string thing2)=0;
    virtual short return_number_for_thing(std::string thing); //virtual is probably not necessary here, I can get rid of it if need be


short BaseClass::return_number_for_thing(std::string thing)
 //pretend thing1 and thing2 are enum'ed somewhere
    if      (thing == thing1) return return_number_for_thing1(thing);
    else if (thing == thing2) return return_number_for_thing2(thing);


class DerivedClass1 : BaseClass

    short return_number_for_thing1(std::string thing1);
    short return_number_for_thing2(std::string thing2);


class DerivedClass2 : BaseClass

    short return_number_for_thing1(std::string thing1);
    short return_number_for_thing2(std::string thing2);

我的问题是,为什么我不能写这样的代码:

short number_i_want = DerivedClass2::return_number_for_thing(thing);

我有点理解尝试从 BaseClass 指针调用 return_number_for_thing 没有意义,因为它不知道是调用 DerivedClass1 还是 DerivedClass2 的例程,但如果我给它 DerivedClass2 的范围,应该它能够弄清楚我想要什么吗?现在,我在需要时创建了一个 DerivedClass2 或 DerivedClass1 的空白实例,但在我看来我不应该这样做。

【问题讨论】:

没有一个方法被声明为static,所以它们需要一个类的实例才能被调用。 没有像静态虚函数这样的东西,句号。 嗯,这是麻烦的一部分。我可以将 return_number_for_thing 声明为静态,但我不能将 return_number_for_thing1 或 return_number_for_thing2 声明为静态,即使在派生类中也是如此,因为编译器告诉我它不能既是虚拟的又是静态的。将 return_number_for_thing 声明为静态是不够的。 拥有多态静态方法简直是个悖论,如果你已经知道类型就不需要多态了吗? πάντα ῥεῖ,如果你喜欢,建议一个不同的标题 【参考方案1】:

在 C++ 中,虚拟和静态不能混用。

virtual = 具体操作取决于对象的类型。 static = 你不需要对象。

当然可以想象这样的事情。如果 C++ 有类似元类型的东西,允许您将常规类型视为对象,那么它就不再是一个奇怪的想法了。

伪代码(使用虚构的语法):

void f(Class base_class)

   base_class.StaticMethod();


struct Base

  virtual static StaticMethod(); // impossible in C++
;

struct Derived : Base

  virtual static StaticMethod(); // impossible in C++
;

f(Base); // impossible in C++
f(Derived); // impossible in C++

创建静态虚函数之类的东西的愿望有时是真正需要的症状(C++ 无法立即满足):将类型视为对象。

【讨论】:

【参考方案2】:

您可以创建一个函数 virtual 或 static ,而不是两者兼而有之。

虚函数必须有一个需要对象实例的 vtable 指针,而静态函数(根据定义)不能有与其相关的实例。

如果您将函数声明为例如:

virtual short return_number_for_thing1(std::string thing1)=0;

那么您必须创建一个实例并使用它,例如m_Instance->return_number_for_thing1(...)(但由于您没有使用任何成员变量,这似乎没有任何意义)。

如果您将函数声明为静态:

static short return_number_for_thing1(std::string thing1)

然后您必须静态调用函数BaseClass::return_number_for_thing1(),如果您在派生类中提供相同函数的静态版本,它现在将成为覆盖,您可以选择在编译时使用BaseClass::return_number_for_thing1 或@ 调用哪个函数987654326@..

您的问题仍然没有真正的意义,因为您不能静态使用虚函数。静态暗示你想在没有任何实例的情况下使用它,它就像一个 c 函数但隐藏在类的命名空间中(并且遵守隐私)。虚函数需要一个实例来操作。

【讨论】:

【参考方案3】:

制作static virtual 方法是不可能的,引用C++11 standard N3337 - 10.3.10:

[ 注意:virtual 说明符意味着成员资格,所以 virtual 函数不能是非成员 (7.1.2) 函数。 虚拟也不能 函数是静态成员,因为虚函数调用依赖于 用于确定调用哪个函数的特定对象。一个虚拟的 在一个类中声明的函数可以在另一个类中声明为友元 班级。 ——尾注]

【讨论】:

显然我的标题已经将注意力从实际问题上移开......我已经更改标题以更能反映我实际尝试做的事情 虚拟函数与实例绑定。您可以创建静态实例(单例)并像这样使用它:DerivedClass2::Instance().return_number_for_thing(thing);

以上是关于使用基类中的函数静态调用纯虚函数的派生类实现的主要内容,如果未能解决你的问题,请参考以下文章

抽象类中的纯虚函数,返回类型为基/派生类型

虚函数和基类中的this指针的问题!

C++ 纯虚函数

多态—— 纯虚函数和抽象类

c++ 虚函数和纯虚函数

C++面试必备