Почему я могу вызывать функции экземпляров статически?

Недавно я просматривал исходный код Notepad ++ на GitHub, и наткнулся вызов метода, как это:

Window::init(hInst, parent);

Я искал функцию, на которую он ссылался, и наткнулся на Window класс- но init функция была отмечена virtualтак ясно это было нестатично. Думая, что я сделал ошибку, я проверил весь заголовок, чтобы убедиться, что не было статической перегрузки initи я убедился, что не было Window.cpp файл. Нет

Пройдя 15 минут вокруг источника, я сдался и git cloned репо локально, чтобы я мог открыть его в Visual Studio. Первое, что я сделал, это собрал, чтобы убедиться, что это не случайное слияние от имени разработчиков проекта — сборка прошла успешно.

Следующие шаги, которые я предпринял:

  • Я открыл файл вызова Window::init и нажал Go To Declaration на Window, Это берет меня к Window учебный класс.

  • Я нажал Go To Declaration на init функция. Это указывает мне на подпись виртуального метода.

  • Я копирую и вставляю Window.h файл в совершенно новый заголовок и заменить все ссылки Window с Foo, Когда я набираю Foo::initкомпилятор жалуется, что «нестатическая ссылка на элемент должна относиться к определенному объекту».

TL; DR: Каким-то образом исходный код Notepad ++ статически вызывает нестатический метод, и это создает. Не работает ни с одним другим классом. доказательство Вот а также Вот.

Я потратил на это 2 часа, но до сих пор не понимаю, как это возможно. Я что-то пропустил?

4

Решение

Нет, это не вызов статической функции. Это просто вызов версии базового класса 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);
}
};
2

Другие решения

Я что-то пропустил?

Да — контекст. Notepad_plus_Window происходит от Windowи призыв к Window::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

Может быть, это будет вас смущать меньше. Вы пропускаете контекст, не по своей вине.

Вы не видите неявное 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;
}

Выше мы можем указать объект, для которого вызывается определенный метод в иерархии классов.

1

Это не статическая функция. Это вызов функции с указанной (классовой) областью действия.

По умолчанию 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;
}
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector