поместить определения функций в заголовочные файлы - PullRequest
14 голосов
/ 20 октября 2011

Если вы хотите поместить определения функций в заголовочные файлы, кажется, есть три различных решения:

  1. пометить функцию как inline
  2. пометить функцию как static
  3. поместите функцию в анонимное пространство имен

(До недавнего времени я даже не знал о # 1.) Так в чем же отличие этих решений, и когда яя должен предпочесть какой?Я в мире только заголовков, поэтому мне действительно нужны определения в заголовочных файлах.

Ответы [ 3 ]

15 голосов
/ 20 октября 2011

Версии static и безымянного пространства имен оказываются одинаковыми: каждая единица перевода будет содержать свою собственную версию функции, а это означает, что для статической функции f указатель &f будет отличаться в каждая единица перевода, и программа будет содержать N разных версий f (больше кода в двоичном виде).

Это не правильный подход для предоставления функции в заголовке, он обеспечит N различными (точно одинаковыми) функциями. Если функция содержит static locals, тогда будут N разные static локальные переменные ...

РЕДАКТИРОВАТЬ : Чтобы сделать это более явным: если вы хотите предоставить определение функции в заголовке, не нарушая Правило Одного Определения, правильный подход - сделать функцию inline .

4 голосов
/ 20 октября 2011

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

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

Указанный стандарт взят из стандарта c ++ 03.

РЕДАКТИРОВАНИЕ:

Следующий пример демонстрирует, почему функции и переменные не должны определяться в безымянном пространстве имен в заголовках:

ops.hpp содержит:

#ifndef OPS_HPP
#define OPS_HPP
namespace
{
int a;
}
#endif

dk1.hpp содержит:

#ifndef DK1_HPP
#define DK1_HPP
void setValue();
void printValue();
#endif

dk1.cpp содержит:

#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>

void setValue()
{
    a=5;
}
void printValue()
{
    std::cout<<a<<std::endl;
}

dk.cpp содержит:

#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>

int main()
{
    // set and print a
    setValue();
    printValue();

    // set and print it again
    a = 22;
    std::cout<<a<<std::endl;

    // print it again
    printValue();
}

Компилировать так:

g++ -ansi -pedantic -Wall -Wextra dk.cpp dk1.cpp

и вывод:

5
22
5

ops переменной a отличается для исходного файла dk1.cpp и dk.cpp

0 голосов
/ 20 октября 2011

static функции (эквивалентные анонимному пространству имен) получают разные копии для каждого TU. Если функция является повторно входящей, она в основном идентична (некоторые компиляторы могут иметь различия на уровне сборки), но если это не так, у нее будут разные статические данные для каждого TU. Встроенные функции свернуты, то есть они имеют только одну копию статических данных для каждого TU.

...