Я занимаюсь разработкой простой библиотеки симуляции и столкнулся с проблемой, где у меня симуляция Time
переменная, которая не должен быть модифицируемым пользователем API (программистом) при любых обстоятельствах (просто предоставить информацию о времени моделирования), но должен быть изменяемым по моделирующей библиотеке, поэтому она не может быть постоянной.
Это то, что я придумал, но мне это кажется немного сложным
double simTime; // Internal time, modified by library
const double& Time = simTime; // Time info provided for programmer in API
Есть ли лучший подход для этого?
Вместо const double &
Вы можете изменить свой API, чтобы обеспечить функцию double getTime();
который возвращает значение simTime
,
Я нахожу 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
Вы могли бы даже (в публичном заголовке) определить некоторые в соответствии функция, возвращающая внешнюю переменную, имя которой достаточно длинное, чтобы ее нельзя было легко угадать, например,
static inline double getTime(void) {
extern double somelongname_simTime; // don't use that name directly
return somelongname_simTime;
}
действительно, имя somelongname_simTime
является общедоступным, но требует непосредственного использования злого умысла (поскольку он не объявлен в области видимости файла в общедоступном заголовочном файле).
(и вы могли бы даже использовать namespace
трюки)
Обратите внимание, что компилятор не может предотвратить неопределенное поведение, такое как указатель, случайно получающий адрес static
переменная.
А в Linux вы могли бы даже поиграть в видимость трюки.
С НКУ конкретно Вы можете попытаться использовать два имени в одной и той же глобальной памяти (используя ассемблерные этикетки), например в вашем публичном заголовке
extern volatile const double simTime_public asm ("myrealsimTime");
и в некотором файле реализации вы будете иметь вместо
double simTime_private asm("myrealsimTime");
Конечно, вы злоупотребляете компилятором и компоновщиком, когда играете в такие трюки.
(и, очевидно, вы могли бы смешать оба подхода).