gpt4 book ai didi

C++无效引用问题

转载 作者:搜寻专家 更新时间:2023-10-31 01:59:57 27 4
gpt4 key购买 nike

我正在用 C++ 编写一些回调实现。

我有一个抽象回调类,比方说:

/** Abstract callback class. */
class callback {
public:

/** Executes the callback. */
void call() { do_call(); };
protected:

/** Callback call implementation specific to derived callback. */
virtual void do_call() = 0;
};

我创建的每个回调(接受单参数函数、双参数函数...)都使用以下之一创建为混合:

/** Makes the callback a single-argument callback. */
template <typename T>
class singleArgumentCallback {
protected:
/** Callback argument. */
T arg;

public:
/** Constructor. */
singleArgumentCallback(T arg): arg(arg) { }
};

/** Makes the callback a double-argument callback. */
template <typename T, typename V>
class doubleArgumentCallback {
protected:
/** Callback argument 1. */
T arg1;

/** Callback argument 2. */
V arg2;

public:
/** Constructor. */
doubleArgumentCallback(T arg1, V arg2): arg1(arg1), arg2(arg2) { }
};

例如,一个单参数函数回调看起来像这样:

/** Single-arg callbacks. */
template <typename T>
class singleArgFunctionCallback:
public callback,
protected singleArgumentCallback<T> {

/** Callback. */
void (*callbackMethod)(T arg);

public:
/** Constructor. */
singleArgFunctionCallback(void (*callback)(T), T argument):
singleArgumentCallback<T>(argument),
callbackMethod(callback) { }

protected:
void do_call() {
this->callbackMethod(this->arg);
}
};

为了方便用户,我希望有一种创建回调的方法,无需用户考虑细节,以便可以调用(不幸的是,此接口(interface)不会更改):

void test3(float x) { std::cout << x << std::endl; }
void test5(const std::string& s) { std::cout << s << std::endl; }

make_callback(&test3, 12.0f)->call();
make_callback(&test5, "oh hai!")->call();

我目前的make_callback(...)实现如下:

/** Creates a callback object. */
template <typename T, typename U> callback* make_callback(
void (*callbackMethod)(T), U argument) {
return new singleArgFunctionCallback<T>(callbackMethod, argument);
}

不幸的是,当我调用 make_callback(&test5, "oh hai!")->call(); 时,我在标准输出上得到了一个空字符串。我认为问题是引用在回调初始化后超出了范围。

我尝试使用指针和引用,但不可能有指针/引用来引用,所以我失败了。我唯一的解决方案是禁止将引用类型替换为 T(例如,T 不能是 std::string&),但这是一个可悲的解决方案,因为我必须创建另一个接受具有以下签名的函数指针的 singleArgCallbackAcceptingReference 类:

void (*callbackMethod)(T& arg);

因此,我的代码被重复了 2^n 次,其中 n 是回调函数的参数数量。

有没有人知道任何解决方法或知道如何解决它?提前致谢!

最佳答案

问题是在make_callback()中,T变成了const std::string&,进而变成了T 在你的 singleArgumentCallback 中。然而,U 是一个 const char*,因此会创建一个临时的 std::string 对象并将其绑定(bind)到 中的该引用singleArgumentCallback。当 make_callback() 完成时,该临时对象被销毁,留下创建的 singleArgumentCallback 对象引用一个不再存在的对象。

您需要做的是首先从传递给 make_callback() 的类型中删除引用(可能还有 cv 限定符)。作为Marcelo suggested , Boost.TypeTraits可以帮助您做到这一点,但如果您愿意,自己制作一些东西并不难:

template< typename T > struct remove_ref     { typedef T result_type; };
template< typename T > struct remove_ref<T&> { typedef T result_type; };

然后将 make_callback() 更改为:

template <typename T, typename U>
callback* make_callback(void (*callbackMethod)(T), U argument)
{
typedef typename remove_ref<T>::result_type arg_type;
return new singleArgFunctionCallback<arg_type>(callbackMethod, argument);
}

关于C++无效引用问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2528618/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com