Відповіді:
В будь-якому місці одного блоку компіляції (як правило, .cpp-файл) буде зроблено:
foo.h
class foo {
static const string s; // Can never be initialized here.
static const char* cs; // Same with C strings.
static const int i = 3; // Integral types can be initialized here (*)...
static const int j; // ... OR in cpp.
};
foo.cpp
#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;
(*) Відповідно до стандартів ви повинні визначитись i
поза визначенням класу (як j
є), якщо воно використовується в коді, відмінному від просто інтегральних постійних виразів. Детальніше дивіться у коментарі Девіда нижче.
i
, її слід було б визначити лише в тому випадку, якщо вона буде використана деінде, ніж у цілісних постійних виразах, правда? У цьому випадку ви не можете сказати, що є помилка, оскільки недостатньо контексту для впевненості - або строго кажучи, що приклад вище є правильним, якщо іншого коду немає. Зараз я ціную ваш коментар (+1), я все ще сам вчусь! Тож я спробую уточнити цю точку у відповіді, будь ласка, дайте мені знати, чи краще ...
int f() { return 42; } class foo { static const int i = f(); /* Error! */ }
Зауважте, що C ++ 11 дозволяє викликати функції "constexpr":constexpr int f() { return 42; } class foo { static const int i = f(); /* Ok */ }
Статичні члени потрібно ініціалізувати в блоці перекладу .cpp в області файлу або у відповідному просторі імен:
const string foo::s( "my foo");
У підрозділі перекладу в одному просторі імен, як правило, вгорі:
// foo.h
struct foo
{
static const std::string s;
};
// foo.cpp
const std::string foo::s = "thingadongdong"; // this is where it lives
// bar.h
namespace baz
{
struct bar
{
static const float f;
};
}
// bar.cpp
namespace baz
{
const float bar::f = 3.1415926535;
}
static const int ARRAYSIZE
У файлі заголовка ініціалізуються лише цілісні значення (наприклад, ), оскільки вони зазвичай використовуються в заголовку класу, щоб визначити щось таке, як розмір масиву. Неінтегральні значення ініціалізуються у файлі реалізації.
i
має бути визначено в cpp. § 9.4.2 / 4 Якщо статичний член даних має інтегральний тип const або перерахунок const, його оголошення у визначенні класу може визначати константа-ініціалізатор, яка має бути інтегральним постійним виразом (5.19). У цьому випадку член може з'являтися в цілісних постійних виразах. Член все ж повинен бути визначений в області простору імен, якщо він використовується в програмі, а визначення обсягу простору імен не повинно містити ініціалізатор.