Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么我可以静态调用实例函数?_C++_Oop_Static_Instance - Fatal编程技术网

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

C++ 为什么我可以静态调用实例函数?,c++,oop,static,instance,C++,Oop,Static,Instance,最近,我在GitHub上查看了Notepad++源代码,以及如下方法调用: Window::init(hInst, parent); 我搜索了它所引用的函数,发现了一个类,但是init函数被标记为virtual,因此它显然是非静态的。考虑到我犯了错误,我检查了整个标题,以确保init没有静态重载,并且确保没有Window.cpp文件。没有 在对源代码进行了15分钟的探索之后,我让步了,并在本地克隆了repo,这样我就可以在visualstudio中打开它了。我做的第一件事就是构建,以确保这不是

最近,我在GitHub上查看了Notepad++源代码,以及如下方法调用:

Window::init(hInst, parent);
我搜索了它所引用的函数,发现了一个类,但是
init
函数被标记为
virtual
,因此它显然是非静态的。考虑到我犯了错误,我检查了整个标题,以确保
init
没有静态重载,并且确保没有
Window.cpp
文件。没有

在对源代码进行了15分钟的探索之后,我让步了,并在本地克隆了repo,这样我就可以在visualstudio中打开它了。我做的第一件事就是构建,以确保这不是代表项目开发人员的意外合并——构建成功了

我接下来采取的步骤是:

  • 我打开文件调用
    窗口::init
    并单击
    窗口上的
    转到声明
    。它把我带到
    窗口

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

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

TL;DR:不知何故,记事本++源代码静态调用了一个非静态方法,这将生成。不适用于任何其他类。证据和证据


我花了两个小时盯着这个,但我仍然不明白这是怎么可能的。我遗漏了什么吗?

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

通常,在派生类中调用虚函数的基类对应项是非常常见的。例如,工厂方法模式:

#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);
   }
};
我错过什么了吗

是-背景
Notepad\u plus\u Window
源自
Window
,对
Window::init()
的调用位于
Notepad\u plus\u Window::init()方法的内部:

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


在这种情况下,
Notepad\u plus\u Window
正在调用
Window的基类
version
init()

,这可能会让您不那么困惑。你失去了背景,不是你自己的错

您在调用中没有看到隐式的
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;
}
#包括
#包括
福班{
公众:
虚拟空心条(){
标准:cout bar
barp->Foo::bar();//->Foo
返回0;
}

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

它不是一个静态函数,而是调用具有指定(类)作用域的函数

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

但是使用指定的类/命名空间前缀,您可以显式调用任何特定函数,而无需动态绑定。例如::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;
}
#包括
甲级
{
公众:
虚空试验()
{

std::cout这就是在重写虚拟函数中调用基函数的方式。啊,真不敢相信我错过了,特别是考虑到类的名称是
Notepad\u plus\u Window
。谢谢!
#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;
}