Статический const double в с ++ - PullRequest
10 голосов
/ 06 мая 2010

Это правильный способ использовать статическую переменную const?В моем классе верхнего уровня (Shape)

#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

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

Ответы [ 7 ]

12 голосов
/ 06 мая 2010

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

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

Хотя есть решение!

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

private:
    double originX;
    double originY;
};

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

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

11 голосов
/ 06 мая 2010

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

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

9 голосов
/ 02 февраля 2013

Если у вас есть способ добавить флаг C++0x в ваш компилятор, вы могли бы сделать:

ifndef SHAPE_H
#define SHAPE_H

class Shape
{
public:

    static constexpr double pi = 3.14159265;
private:
    double originX;
    double originY;
};

#endif

В C++0x вы можете использовать выражения const для типов, отличных от целочисленных. Это позволяет вам объявить и определить на месте вашу постоянную переменную.

3 голосов
/ 06 мая 2010

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

1 голос
/ 06 мая 2010

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

0 голосов
/ 17 июня 2017

Реализуйте функцию, которая возвращает индекс значения в список, если он существует. В противном случае верните -1, если значения нет. Если одно и то же значение присутствует в списке более одного раза, первое значение удаляется снизу.

public static intfindFromLast (List <Double> l, double value ) {///…}
0 голосов
/ 06 мая 2010

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

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

private:
    double originX;
    double originY;
};

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

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

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