C++ 为什么我可以静态调用实例函数?
最近,我在GitHub上查看了Notepad++源代码,以及如下方法调用:C++ 为什么我可以静态调用实例函数?,c++,oop,static,instance,C++,Oop,Static,Instance,最近,我在GitHub上查看了Notepad++源代码,以及如下方法调用: Window::init(hInst, parent); 我搜索了它所引用的函数,发现了一个类,但是init函数被标记为virtual,因此它显然是非静态的。考虑到我犯了错误,我检查了整个标题,以确保init没有静态重载,并且确保没有Window.cpp文件。没有 在对源代码进行了15分钟的探索之后,我让步了,并在本地克隆了repo,这样我就可以在visualstudio中打开它了。我做的第一件事就是构建,以确保这不是
Window::init(hInst, parent);
我搜索了它所引用的函数,发现了一个类,但是init
函数被标记为virtual
,因此它显然是非静态的。考虑到我犯了错误,我检查了整个标题,以确保init
没有静态重载,并且确保没有Window.cpp
文件。没有
在对源代码进行了15分钟的探索之后,我让步了,并在本地克隆了repo,这样我就可以在visualstudio中打开它了。我做的第一件事就是构建,以确保这不是代表项目开发人员的意外合并——构建成功了
我接下来采取的步骤是:
- 我打开文件调用
并单击窗口::init
窗口上的
。它把我带到转到声明
类窗口
- 我在
函数上单击了init
。它指向虚拟方法的签名Go To Declaration
- 我将
文件复制并粘贴到一个全新的头文件中,并将Window.h
的所有引用替换为Window
。当我输入Foo
时,编译器会抱怨“非静态成员引用必须相对于特定对象”Foo::init
我花了两个小时盯着这个,但我仍然不明白这是怎么可能的。我遗漏了什么吗?不,它没有调用静态函数。它只是调用基类版本的
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的基类versioninit()
,这可能会让您不那么困惑。你失去了背景,不是你自己的错
您在调用中没有看到隐式的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;
}