请考虑以下代码:
struct data
{
int foo;
int bar;
};
data a;
a.foo = 200;
a.bar = 300;
static void update(data* a, int rspec)
{
if (!rspec) //my data management
{
3rdPartyApi->CreateStream();
3rdPartyApi->PushData(a->foo);
3rdPartyApi->PushData(a->bar);
3rdPartyApi->CloseStream();
}
else // internal data management
{
3rdPartyApi->CreateStream();
3rdPartyApi->PushData(3rdPartyApi->BufferQueue);
3rdPartyApi->CloseStream();
}
3rdPartyApi->PushStream(3rdPartyApi->GetLastStreamBuffer().POD());
}
假设我改变了a.foo或a.bar的值,它要求我在分配后调用Update。可以这样做,而不是手动调用每个更改的Update()吗?
[编辑]
请注意,创建的更新函数也分配给函数指针
第三方API,因此它可以自己进行内部更新。因此,使更新函数非全局化是不可能的,因此当前更新函数是全局的
[编辑]
我还重写了我的例子,以便更加理解和纠正我正在使用的实际API
e.g
3rdPartyApi->StreamUpdate((void (*)(void*, int))update);
答案 0 :(得分:4)
是的,你可以。为此使用类方法。将类中的静态方法作为更新函数传递给第三方API。
class data
{
public:
void set_foo(int new_foo);
void set_bar(int new_bar);
int get_foo() const;
int get_bar() const;
// This is the update signature which the 3rd party API can accept.
static void update(void* ptr, int rspec);
private:
// These are private so we can control their access.
int foo;
int bar;
};
void data::set_foo(int new_foo)
{
foo = new_foo;
// 'this' is a special pointer for current data object.
update(this);
}
void data::set_bar(int new_bar)
{
bar = new_bar;
update(this);
}
int data::get_foo() const
{
return foo;
}
int data::get_bar() const
{
return bar;
}
// This is needed if the 3rd party API can only call C bindings.
// If it's a C++ API this is not needed.
extern "C" {
void data::update(void* ptr, int rspec)
{
if (!rspec) //my data management
{
// You have to cast to data* from void*.
data* data_ptr = reinterpret_cast<data*>(ptr);
3rdPartyApi->CreateStream();
3rdPartyApi->PushData(data_ptr->foo);
3rdPartyApi->PushData(data_ptr->bar);
3rdPartyApi->CloseStream();
}
else // internal data management
{
3rdPartyApi->CreateStream();
3rdPartyApi->PushData(3rdPartyApi->BufferQueue);
3rdPartyApi->CloseStream();
}
3rdPartyApi->PushStream(3rdPartyApi->GetLastStreamBuffer().POD());
}
} /* extern "C" */
然后:
3rdPartyApi->StreamUpdate(&data::update);
data a;
a.set_foo(200);
a.set_bar(300);
请注意,使用struct
代替class
同样适用。但惯例是使用C ++中的类。稍后您只能学到一些细微差别。
答案 1 :(得分:2)
很难为foo,bar和data编写代码,所以让它更具体:
class point
{
public:
int x_coord() const;
int y_coord() const;
void move_to(int new_x, int new_y);
private:
void update_3rd_party();
int x;
int y;
};
void point::move_to(int new_x, int new_y)
{
x = new_x;
y = new_y;
// whatever else needs to be done
update_3rd_party();
}
答案 2 :(得分:1)
答案 3 :(得分:1)
通常的方法是将foo
和bar
转换为重载赋值运算符的某种类型:
class updated_int {
int value;
public:
updated_int(int init = 0) : value(init) {}
updated_int &operator=(int new_val) {
value = new_val;
update();
return *this;
}
// You might want to declare this private and not implement it.
updated_int &operator=(updated_int const &r) {
value = r.value;
update();
return *this;
}
operator int() { return value; }
};
struct data {
updated_int foo;
updated_int bar;
}
data a;
a.foo = 1; // operator= will call update() automatically.