将指向不同变量类型的指针传递给一个函数,并在以后重用它们进行赋值
Passing pointers to different variable types to a function and reuse them later for assignmet
在一个基于 GUI 的项目中,我需要 Page1 标记一个变量 要更改 并调用 Page2,Page2 读取用户的输入并用新值更新标记的变量。
变量类型始终不同,所有变量都由外部链接库保存。
如何在不为标记和设置器创建 fname_uint8、fname_uint16、fname_giventype 变体的情况下实现这一目标?
这个例子总结了场景:
有一个 VarHolder
class 包含很多结构和很多变量,例如:
class VarHolder
{
public:
typedef struct {
int8_t var1;
int16_t var2;
int32_t var3;
char str1[40];
float var4;
} struct1_t;
/* ...continues... */
struct1_t struct1;
}
现在 class FirstStage
想要标记一个变量进行更改,并调用 class Committer
committer_instance
实例的成员
class FirstStage
{
/* ... */
void doFirstStage(void)
{
/* Globally defined committer instance */
g_committer_instance->mark_var_change(&varholder_instance->struct1.var1);
}
}
Committer::mark_var_change(T*)
定义如下:
template <typename T>
void Committer::mark_var_change(T *var)
{
/* Store a pointer to the variable */
/* SAVE SOMEWHERE PRESERVING TYPE */ = var;
}
SecondStage
的一个成员,最后,想要使用一个现在可用的值来更新标记为更改的变量,通过相同的 g_committer_instance
,像这样:
class SecondStage
{
/* ... */
template <typename T>
void doSecondStage(T new_value)
{
g_committer_instance->commit_change(new_value);
}
}
其中Committer::commit_change(T)
定义如下:
template <typename T>
void Committer::commit_change(T new_value)
{
/* Dereferencing the previously stored pointer */
*(/*WHATEVER I STORED BEFORE*/) = new_value;
}
当然我不能做的是实现一个类型独立的"marker and retriever",它可以根据地址无缝更新变量。
非常感谢任何建议。
MCVE
### varholder.h
#include <stdint.h>
class VarHolder
{
public:
VarHolder() {}
virtual ~VarHolder() {}
typedef struct
{
int8_t var1;
uint8_t var2;
int64_t var3;
char str1[40];
} struct1_t;
struct1_t struct1;
}
### firststage.h
#include global.h
class FirstStage
{
public:
FirstStage() {}
~FirstStage() {}
void doFirstStage(void)
{
/* Globally defined committer instance */
g_committer_instance->mark_var_change(&varholder_instance->struct1.var1);
}
}
### secondstage.h
#include global.h
class SecondStage
{
public:
SecondStage() {}
~SecondStage() {}
template <typename T>
void doSecondStage(T new_value)
{
g_committer_instance->commit_change(new_value);
}
}
### committer.h
#include global.h
class Committer
{
public:
Committer() {}
~Committer() {}
template <typename T>
void Committer::mark_var_change(T *var)
{
/* Store a pointer to the variable */
/* SAVE SOMEWHERE PRESERVING TYPE */ = var;
}
template <typename T>
void Committer::commit_change(T new_value)
{
/* Dereferencing the previously stored pointer */
*(/*WHATEVER I STORED BEFORE*/) = new_value;
}
}
### global.h
#include varholder.h
#include committer.h
extern Committer *g_committer_instance;
extern VarHolder *varholder_instance;
### main.cpp
#include global.h
#include varholder.h
#include firststage.h
#include secondstage.h
Committer *g_committer_instance;
VarHolder *varholder_instance;
int main()
{
g_committer_instance = new Committer();
varholder_instance = new VarHolder();
FirstStage *fstage = new FirstStage();
SecondStage *sstage = new SecondStage();
int8_t var_new = 100;
/* First stage */
fstage->doFirstStage();
/* Second stage */
sstage->doSecondStage(var_new);
return 0;
}
您可以在不使用(不安全)或使用 typeid
的情况下使用 void*
:
class Committer
{
public:
template <typename T>
void mark_var_change(T *var)
{
mPointer = var;
mTypeInfo = &typeid(T*);
}
template <typename T>
void commit_change(T new_value)
{
if (*mTypeInfo != typeid(T*)) {
throw std::runtime_error("Bad type");
}
if (mPointer == nullptr) {
throw std::runtime_error("nullptr was stocked");
}
*reinterpret_cast<T*>(mPointer) = new_value;
}
private:
void* mPointer = nullptr;
const std::type_info* mTypeInfo = nullptr;
};
- 没有 typeid Live example
- 带 typeid Live example
或更安全的 boost::any
自行管理类型:
class Committer
{
public:
template <typename T>
void mark_var_change(T *var)
{
mPointer = var;
}
template <typename T>
void commit_change(T new_value)
{
T* pointer = boost::any_cast<T*>(mPointer); // throw with bad type
if (pointer == nullptr) {
throw std::runtime_error("nullptr was stocked");
}
*pointer = new_value;
}
private:
boost::any mPointer;
};
在一个基于 GUI 的项目中,我需要 Page1 标记一个变量 要更改 并调用 Page2,Page2 读取用户的输入并用新值更新标记的变量。 变量类型始终不同,所有变量都由外部链接库保存。
如何在不为标记和设置器创建 fname_uint8、fname_uint16、fname_giventype 变体的情况下实现这一目标?
这个例子总结了场景:
有一个 VarHolder
class 包含很多结构和很多变量,例如:
class VarHolder
{
public:
typedef struct {
int8_t var1;
int16_t var2;
int32_t var3;
char str1[40];
float var4;
} struct1_t;
/* ...continues... */
struct1_t struct1;
}
现在 class FirstStage
想要标记一个变量进行更改,并调用 class Committer
committer_instance
实例的成员
class FirstStage
{
/* ... */
void doFirstStage(void)
{
/* Globally defined committer instance */
g_committer_instance->mark_var_change(&varholder_instance->struct1.var1);
}
}
Committer::mark_var_change(T*)
定义如下:
template <typename T>
void Committer::mark_var_change(T *var)
{
/* Store a pointer to the variable */
/* SAVE SOMEWHERE PRESERVING TYPE */ = var;
}
SecondStage
的一个成员,最后,想要使用一个现在可用的值来更新标记为更改的变量,通过相同的 g_committer_instance
,像这样:
class SecondStage
{
/* ... */
template <typename T>
void doSecondStage(T new_value)
{
g_committer_instance->commit_change(new_value);
}
}
其中Committer::commit_change(T)
定义如下:
template <typename T>
void Committer::commit_change(T new_value)
{
/* Dereferencing the previously stored pointer */
*(/*WHATEVER I STORED BEFORE*/) = new_value;
}
当然我不能做的是实现一个类型独立的"marker and retriever",它可以根据地址无缝更新变量。 非常感谢任何建议。
MCVE
### varholder.h
#include <stdint.h>
class VarHolder
{
public:
VarHolder() {}
virtual ~VarHolder() {}
typedef struct
{
int8_t var1;
uint8_t var2;
int64_t var3;
char str1[40];
} struct1_t;
struct1_t struct1;
}
### firststage.h
#include global.h
class FirstStage
{
public:
FirstStage() {}
~FirstStage() {}
void doFirstStage(void)
{
/* Globally defined committer instance */
g_committer_instance->mark_var_change(&varholder_instance->struct1.var1);
}
}
### secondstage.h
#include global.h
class SecondStage
{
public:
SecondStage() {}
~SecondStage() {}
template <typename T>
void doSecondStage(T new_value)
{
g_committer_instance->commit_change(new_value);
}
}
### committer.h
#include global.h
class Committer
{
public:
Committer() {}
~Committer() {}
template <typename T>
void Committer::mark_var_change(T *var)
{
/* Store a pointer to the variable */
/* SAVE SOMEWHERE PRESERVING TYPE */ = var;
}
template <typename T>
void Committer::commit_change(T new_value)
{
/* Dereferencing the previously stored pointer */
*(/*WHATEVER I STORED BEFORE*/) = new_value;
}
}
### global.h
#include varholder.h
#include committer.h
extern Committer *g_committer_instance;
extern VarHolder *varholder_instance;
### main.cpp
#include global.h
#include varholder.h
#include firststage.h
#include secondstage.h
Committer *g_committer_instance;
VarHolder *varholder_instance;
int main()
{
g_committer_instance = new Committer();
varholder_instance = new VarHolder();
FirstStage *fstage = new FirstStage();
SecondStage *sstage = new SecondStage();
int8_t var_new = 100;
/* First stage */
fstage->doFirstStage();
/* Second stage */
sstage->doSecondStage(var_new);
return 0;
}
您可以在不使用(不安全)或使用 typeid
的情况下使用 void*
:
class Committer
{
public:
template <typename T>
void mark_var_change(T *var)
{
mPointer = var;
mTypeInfo = &typeid(T*);
}
template <typename T>
void commit_change(T new_value)
{
if (*mTypeInfo != typeid(T*)) {
throw std::runtime_error("Bad type");
}
if (mPointer == nullptr) {
throw std::runtime_error("nullptr was stocked");
}
*reinterpret_cast<T*>(mPointer) = new_value;
}
private:
void* mPointer = nullptr;
const std::type_info* mTypeInfo = nullptr;
};
- 没有 typeid Live example
- 带 typeid Live example
或更安全的 boost::any
自行管理类型:
class Committer
{
public:
template <typename T>
void mark_var_change(T *var)
{
mPointer = var;
}
template <typename T>
void commit_change(T new_value)
{
T* pointer = boost::any_cast<T*>(mPointer); // throw with bad type
if (pointer == nullptr) {
throw std::runtime_error("nullptr was stocked");
}
*pointer = new_value;
}
private:
boost::any mPointer;
};