3

我正在尝试执行以下操作:从函数中本地定义的类中获取成员函数的地址。

class ConnectionBase
{
};

template class<EventType, SinkType>
class ConnectionImpl : public ConnectionBase
{
public:
typedef void (SinkType::*EventCallback)(EventType const&);
};


template<class EventType>
class Source
{
    template <class SinkType>
    boost::shared_ptr<ConnectionBase> setupCallback(typename ConnectionImpl<EventType, SinkType>::EventCallback func, SinkType* sink)
    {
    // do the actual connecting.
    }
};

class SomeClass
{
public:
    void someFunction(int const& event){}
}

class SomeUnitTest
{
public:
    void someTest()
    {
        class NestedClass 
        {
        public:
            void someFunction(int const& event){}
        };

       NestedClass nc;

       //Try#1 - This does not work
       setupCallback<int, NestedClass>(&NestedClass::someFunction, &nc);

       //Try #2 - This also does not work
       setupCallback<int, NestedClass>(&SomeUnitTest::someTest::NestedClass::someFunction, &nc);

       //Try #3 - Following the GCC error output, I tried this
       setupCallback<int, NestedClass>(&SomeUnitTest::someTest()::NestedClass::someFunction, &nc);

       SomeClass sc;

       //This works fine, as expected
       setupCallback<int, SomeClass>(&SomeClass::someFunction, &sc);

    }
};

尝试 #2 和 #3 完全混淆 GCC,它不知道我要做什么。Try #1 会生成一条更有用的错误消息,指出不存在 setupCallback,其形式为“setupCallback(void (SomeUnitTest::someTest()::NestedClass::SomeFunction::*), etc) 这就是 try #3 的诞生方式。

我真的找不到很多关于函数内部定义的类的信息,有没有人知道正确的语法,并且可能有讨论这个主题的资源?

好的,看来这已经解决了,正如两位发帖人所指出的,本地类没有链接,它不能工作。现在知道了这一点,我发现这篇文章讨论了这个问题,对于遇到这个问题并偶然发现这个问题的任何人:http: //www.informit.com/guides/content.aspx? g=cplusplus&seqNum=420

编辑:setupCallback() 的说明,使用更常规的类的工作示例
编辑#2:更新措辞以将“嵌套”更改为“本地”。为 setupCallback 添加了更多详细信息。
编辑#3:添加了更多信息的链接。谢谢大家。

4

2 回答 2

4

我不知道语法问题,应该应用通常的访问规则 - 但是如果这样可以工作,那么这里还有另一个问题,因为这些成员函数没有链接。
要完全接受本地类型,setupCallback()必须是模板函数 - 但不允许没有链接的模板类型参数。

§3.5/8说:

这些规则未涵盖的名称没有联系。此外,除非另有说明,在本地范围 (3.3.2) 中声明的名称没有链接。

本地类的成员不包括在内。§9.3/3阐明:

本地类 (9.8) 的成员函数没有链接。

长话短说:不要使用本地类的成员函数作为回调,而是使用非本地类。

于 2010-01-28T07:20:32.413 回答
4

只要考虑到获取地址的具体问题,您的第一个变体就是正确的变体。获取本地类的成员函数的地址没有限制。正确的语法是通常的

&NestedClass::someFunction

就是这样。您可以尝试将其保存在代码中的中间指针中

void (NestedClass::*ptr)() = &NestedClass::someFunction;

我相信你的编译器会接受它。

但是,我怀疑您的代码中存在的问题与获取成员函数地址的正确方法完全无关。而是关于setupCallback声明第一个参数的方式。既然你说它可以&SomeClass::someFunction作为第一个参数,我希望setupCallback被声明为

void setupCallback(void (SomeClass::*cb)(), SomeClass *p); // one possibility

即,它是硬编码的,以期望一个指向SomeClass特定成员的指针。您不能提供指向成员的指针NestedClassNestedClass完全不相关SomeClass,指向成员的指针NestedClass与指向成员的指针完全不兼容SomeClass。这就是它无法编译的原因。

除非您没有向我们展示某些内容(例如setupCallback可能是函数模板?或者为不同的参数类型重载?),否则无论您如何获取成员地址,只要NestedClass保持不相关,您都无法实现到SomeClass. 函数setupCallback被设计为SomeClass只能SomeClass使用。

提供有关setupCallback. 它是如何声明的?

请注意,如果setupCallback被声明为按类类型参数化的函数模板,如

template <class T> void setupCallback(void (T::*cb)(), T* p);

那么您将无法将本地类NestedClass用作参数的模板参数T。在这种情况下,您NestedClass没有联系的事实确实发挥了作用。但是,同样,它与获取成员地址无关,而是由于没有链接的类不能用作 C++ 中的模板参数这一事实。

于 2010-01-28T07:47:10.497 回答