Статическая константа дважды в C++

Действительно ли это - надлежащий способ использовать статическую переменную константы? В моем высокоуровневом классе (Форма)

#ifndef SHAPE_H
#define SHAPE_H

class Shape
{
public:

    static const double pi;
private:
    double originX;
    double originY;
};

const double Shape::pi = 3.14159265;

#endif

И затем позже в классе, который расширяет Форму, я использую Форму:: пи. Я получаю ошибку компоновщика. Я переместил константу двойная Форма:: пи = 3.14... в файл Shape.cpp и мою программу затем компилирует. Почему это происходит?спасибо.

10
задан KARTHIKEYAN.A 3 January 2018 в 10:05
поделиться

5 ответов

Поскольку const double Shape :: pi = 3.14159265; - это определение Shape :: pi , а C ++ допускает только одно определение символа (называется правилом одного определения , которое вы можете увидеть в его сокращенной форме ODR). Когда определение находится в файле заголовка, каждая единица перевода получает собственное определение, которое нарушает это правило.

Переместив его в исходный файл, вы получите только одно определение.

11
ответ дан 3 December 2019 в 14:10
поделиться

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

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

Но решение есть!

class Shape
{
public:
    static double pi()
        { return 3.14159265; }

private:
    double originX;
    double originY;
};

Встроенные определения функций, в том числе статические, разрешены внутри блока class {} .

Также я рекомендую использовать M_PI из , который вы также должны получить из .

12
ответ дан 3 December 2019 в 14:10
поделиться

Это происходит из-за того, что вы не можете определить Shape :: pi более одного раза. Он определяется один раз, когда вы включаете Shape.h в Shape.cpp, а затем снова каждый раз, когда вы используете Shape.h в другом файле cpp. Когда вы идете связать вашу программу вместе, компоновщик заблокируется из-за нескольких определений.

3
ответ дан 3 December 2019 в 14:10
поделиться

Строка const double Shape::pi = 3.14159265; должна быть в вашем файле Shape.cpp. Заголовочный файл предназначен для объявления переменных. Вы можете определить переменную только один раз, поэтому это должно быть сделано в .cpp. В заголовочном файле говорится, как использовать эти переменные и функции, а в файле cpp - что делать.

1
ответ дан 3 December 2019 в 14:10
поделиться

Для примитивных типов данных (таких как int, double, но не char []) вы также можете определить константу в определении класса в файле заголовка, например:

class Shape
{
public:
    static const double pi = 3.14159265;

private:
    double originX;
    double originY;
};

Это позволит лучше оптимизировать компилятор.

Изменить: Как указал Деннис ниже, это разрешено только для целочисленных типов, но не для типов данных double или float (однако некоторые компиляторы это допускают).

0
ответ дан 3 December 2019 в 14:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: