Экстерьер для метода класса - PullRequest
0 голосов
/ 10 марта 2020

Я хочу использовать ключевое слово extern для метода класса в C ++. Я использую Visual Studio 2019.
Я хочу принудительно включить метод, используя __forceinline (без extern я получу неразрешенный внешний символ). Я не хочу помещать реализацию метода в этот заголовочный файл, я хочу поместить реализацию в другой файл. cpp.
Я заметил, что метод может быть встроен автоматически без extern и __forceinline и когда реализация метода в. cpp файл. Как я могу форсировать это?
Пример кода:

class Window {
public:
  void Show();
};

Это нормально!

class Window {
public:
  __forceinline void Show();
};

Получает неразрешенный внешний символ при вызове этой функции из других CPP.
С extern я получаю: скриншот

Для простых функций extern __forceinline работает отлично: скриншот

Ответы [ 3 ]

1 голос
/ 10 марта 2020

Нельзя указать extern для функции-члена.

Стандарт поясняет это в [dcl.stc]/5:

Спецификатор extern может применяться только к именам переменных и функции. Спецификатор extern нельзя использовать в объявлении членов класса или параметров функции.

Когда вы используете extern, вы говорите компилятору, что вы объявляете переменную или функцию, но не определяете их. В случае функций-членов это не требуется: они всегда могут быть объявлены в теле класса без определения:

class A { 
public: 
       void f();  // you can define it in which ever compilation unit (cpp) you want
};  
...
// Else where...may be in another cpp
void A::f() {...} 

Компоновщик разрешит символы при необходимости.

Встроенный не очень полезен

Стандарт в [dcl.inline]/2 говорит, что встроенный не гарантируется:

Встроенный спецификатор указывает реализации, что встроенная замена тела функции в точке вызова должно быть предпочтительнее обычного механизма вызова функции. Реализация не требуется для выполнения этой внутренней подстановки в точке вызова;

Кроме того, [dcl.inline]/6 объясняет, что inline и определенные eleswhere не предназначены для работы хорошо:

Встроенная функция или переменная должна быть определена в каждой единице перевода, в которой она используется odr, и должна иметь абсолютно одинаковое определение в каждом случае.

(odr говорит, что все определения должны каждый раз быть точно таким же определением) (в каждой единице перевода означает в каждом cpp или включенных в него заголовках)

На С другой стороны, глобальный оптимизатор некоторых современных компиляторов способен достичь тех же эффектов производительности, что и встроенные функции, и это распространяется на единицы компиляции (cpp).

Спецификация реализации c forceinline

MSV C 2019 тщательно использует inline, проводя анализ затрат / выгод, чтобы решить, стоит ли включать.

forceinline позволяет вам отменить решение компилятора. Но он отвечает всем требованиям обычного inline: поэтому вам нужно иметь определение функции в том же модуле компиляции, чтобы она заработала.

0 голосов
/ 11 марта 2020

Я не хочу помещать реализацию метода в этот заголовочный файл, я хочу поместить реализацию в другой файл. cpp.

Звучит так, будто вы просто хотите иметь все объявления в одном файле, например:

Это ваш window.h - файл:

class Window 
{
public:
  void Show();
};

Чтобы иметь реализацию в другом файле, вы должны использовать оператор области действия. Это другой window.cpp - файл, в котором у вас есть фактическая реализация функции:

#include "window.h"

Window::Show()
{
    // Your implementation goes here
}

Надеюсь, я правильно понял ваш вопрос, и это поможет.

0 голосов
/ 10 марта 2020

Две вещи:

  1. Вы не можете объявить функцию-член как extern. Они уже имеют внешнюю связь.

  2. Чтобы компилятор встроил функцию или метод, он должен быть определен (в отличие от объявленного) в заголовочном файле. Это сделано для того, чтобы компилятор мог видеть это при компиляции кода, вызывающего функцию.

Итак, просто поместите тело функции в файл заголовка и удалите extern.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...