为什么我可以静态调用实例函数?

时间:2015-07-23 02:07:29

标签: c++ oop static instance

我最近在GitHub上查看Notepad ++源代码,came across这样的方法调用:

Window::init(hInst, parent);

我搜索了它引用的函数,并遇到Window类 - 但init函数标记为virtual,所以很明显它是非静态的。想到我犯了一个错误,我检查了整个标头,以确保没有init的静态重载,我确保没有Window.cpp文件。没有。

在源码周围探索了15分钟之后,我在本地放入了git cloned repo,因此我可以在Visual Studio中打开它。我做的第一件事就是构建以确保代表项目开发人员不会意外合并 - 构建成功。

我接下来的步骤:

  • 我打开了调用Window::init的文件,然后点击Go To Declaration上的Window。我需要Window课程。

  • 我在Go To Declaration函数上点击了init。它指出了虚拟方法的签名。

  • 我将Window.h文件复制并粘贴到一个全新的标头中,并将Window的所有引用替换为Foo。当我输入Foo::init时,编译器会抱怨'非静态成员引用必须与特定对象相关'。

TL; DR:不知何故,Notepad ++源代码静态调用非静态方法,并构建此方法。不适用于任何其他类。证明herehere

我花了2个小时盯着这个,但我仍然没有看到它是如何可能的。我错过了什么吗?

4 个答案:

答案 0 :(得分:2)

不,它没有调用静态函数。它只是调用基类的init()版本。基本上,在tClassName::f中,您要求"我想在课程f()"中调用虚拟函数tClassName的特定版本。

通常,在派生类中调用基类的虚函数副本是很常见的。例如,工厂方法模式:

#include "tObject.h"
#include "tObject1.h" // public inheritance from tObject
#include "tObject2.h" // public inheritance from tObject
#include "tObject3.h" // public inheritance from tObject

class BaseFactory
{
public:
   // factory method
   virtual tNode *createObject(int id)
   {
      if (id == 1) return new tObject1;
      else return new tObject2;
   }
};

class DerivedFactory: public BaseFactory
{
public:
   virtual tNode *createObject(int id)
   {
      // Overrides the default behavior only for one type
      if (id == 1) return new tObject3;
      // Call the default factory method for all other types
      else return BaseFactory::createObject(id);
   }
};

答案 1 :(得分:2)

  

我错过了什么吗?

是 - 背景。 Notepad_plus_Window来自WindowWindow::init()的调用位于Notepad_plus_Window::init()方法内:

class Notepad_plus_Window : public Window { 
public: 
    ...
    void init(HINSTANCE, HWND, const TCHAR *cmdLine, CmdLineParams *cmdLineParams); 
    ...
};

void Notepad_plus_Window::init(HINSTANCE hInst, HWND parent, const TCHAR *cmdLine, CmdLineParams *cmdLineParams) 
{ 
    ...
    Window::init(hInst, parent); 
    ...
}

在此上下文中,Notepad_plus_Window正在调用Window的基类init()版本。

答案 2 :(得分:1)

这可能会让你更加困惑。你错过了背景,没有你自己的错误。

您没有在通话中看到隐含的this

采用以下示例:

#include <cstdio>
#include <iostream>

class Foo {
public:
  virtual void bar() {
    std::cout << "Foo" << std::endl;
  }
};

class Bar : public Foo {
public:
  virtual void bar() {
    std::cout << "Bar" << std::endl;
  }
};

int main() {
  Bar bar;
  bar.bar();        //-> bar
  bar.Foo::bar();   //-> foo

  Bar *barp = &bar;
  barp->bar();      //-> bar
  barp->Foo::bar(); //-> foo

  return 0;
}

在上面,我们可以指定在类的层次结构中调用特定方法的对象。

答案 3 :(得分:1)

这不是静态功能。它正在调用具有指定(类)范围的函数。

默认情况下,init()将匹配当前类范围内的函数(如果它们确实存在)。这是一个隐含的调用,等于this-&gt; init(),

但是使用指定的类/名称空间前缀,您可以显式调用任何特定函数而无需动态绑定。 ie :: init()将在全局范围内调用init()函数。

以下代码可能会让您更好地理解

#include <iostream>

class A
{
public:
  virtual void  test()
  {
      std::cout << "A" << std::endl;
  }
};

class B : public A
{
public:
    virtual void test()
    {
        std::cout << "B" << std::endl;
    }
};

int main()
{
    A* a = new B();
    a->A::test();
    return 0;
}