Как создать внешне неизменяемую переменную? - PullRequest
0 голосов
/ 29 декабря 2018

Я занимаюсь разработкой простой библиотеки симуляции и столкнулся с проблемой, где у меня есть переменная симуляции Time, которую не следует изменять пользователем API (программистом) при любых обстоятельствах (просто предоставьте информацию овремя симуляции), но должна быть модифицируемой библиотекой симуляции, поэтому она не может быть постоянной.

Это то, что я придумал, но мне это кажется немного сложным

double simTime;                // Internal time, modified by library
const double& Time = simTime;  // Time info provided for programmer in API

Есть ли лучший подход к этому?

Ответы [ 3 ]

0 голосов
/ 29 декабря 2018

Я нахожу решение const double& довольно простым и элегантным, и не вижу никаких негативных побочных эффектов.

Единственное, что ваша библиотека должна объявить simTime либо static или в анонимном пространстве имен, так что к нему нельзя обратиться извне.В противном случае любой extern double simTime в любой другой единице перевода выставит simTime.

Так что напишите ...

// library.cpp:
static double simTime;
const double &simTimePublic = simTime;

// library.h:
extern const double &simTimePublic;

// userCode.cpp:
#include "library.h"
...
double simTimeCopy = simTimePublic;

// simTimePublic = 1.0; // illegal
0 голосов
/ 31 декабря 2018

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

static inline double getTime(void) {
  extern double somelongname_simTime; // don't use that name directly
  return somelongname_simTime;
}

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

(и вы даже можете использовать namespace трюки)

Обратите внимание, что компилятор не может предотвратить неопределенное поведение, такое как указатель, случайно получающий адрес переменной static.

А в Linux вы даже можете сыграть некоторую visibility трюки.


С GCC специально вы можете попытаться использовать два имени в одной и той же глобальной памяти (используя метки ассемблера * 1025)*), например, в вашем общедоступном заголовке

extern volatile const double simTime_public asm ("myrealsimTime");

и в каком-то файле реализации вы будете иметь вместо этого

double simTime_private asm("myrealsimTime");

Конечно, вы злоупотребляете компилятором и компоновщиком, когда играете такие трюки.

(и, очевидно, вы могли бы смешать оба подхода).

0 голосов
/ 29 декабря 2018

Вместо const double & вы можете изменить свой API для предоставления функции double getTime();, которая возвращает значение simTime.

...