简体   繁体   English

如何获取函数(C ++)中定义的本地类的成员函数的地址

[英]How to get address of member function for local class defined in function (C++)

I am trying to do the following: Obtain the address of a member function from a class that was locally defined within a function. 我正在尝试执行以下操作:从在函数内本地定义的类中获取成员函数的地址。

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);

    }
};

Try #2 and #3 utterly confuse GCC, it has no idea what I am trying to do. 尝试#2和#3完全混淆GCC,但不知道我要做什么。 Try #1 produces a more helpful error message saying no setupCallback exists that takes the form "setupCallback(void (SomeUnitTest::someTest()::NestedClass::SomeFunction::*), etc) Which is how try #3 was born. 尝试#1会产生一条更有用的错误消息,提示不存在setupCallback,其格式为“ setupCallback(void(SomeUnitTest :: someTest():: NestedClass :: SomeFunction :: *)等),这就是尝试#3的诞生方式。

I can't really find a lot of information about classes defined inside a function, does anyone know the correct syntax for this, and maybe have a resource that discusses this topic? 我真的找不到关于函数内部定义的类的大量信息,有人知道此语法的正确性吗,也许有讨论此主题的资源?

Ok, it appears this is settled, as both posters have pointed out, local classes have no linkage, it can't work. 好的,看来这已经解决了,正如两位发帖人所指出的那样,本地班级没有联系,这是行不通的。 Now knowing this, I found this article that discusses this, for anyone else that runs into this problem and stumbles across this question: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=420 现在知道了这一点,我发现这篇文章讨论了此问题,适用于遇到此问题并偶然发现此问题的其他任何人: http : //www.informit.com/guides/content.aspx? g=cplusplus&seqNum=420

Edit: Clarification of setupCallback(), working example with a more regular class 编辑:澄清setupCallback(),使用更常规类的工作示例
Edit #2: Updated wording to change "nested" to "local". 编辑#2:更新了措辞,将“嵌套”更改为“本地”。 Added more detail for setupCallback. 为setupCallback添加了更多详细信息。
Edit #3: Added links to furhter information. 编辑#3:添加了指向更多信息的链接。 Thanks everyone. 感谢大家。

I don't know about the syntax problem, the usual access rules should apply - but there is another problem here if that would work as these member functions have no linkage. 我不知道语法问题,应该使用通常的访问规则-但是这里存在另一个问题,因为这些成员函数没有链接,是否可以使用。
To accept local types at all, setupCallback() would have to be a template function - but template type arguments with no linkage are not allowed. 要完全接受本地类型, setupCallback()必须是模板函数-但是不允许使用没有链接的模板类型参数。

§3.5/8 says: §3.5/ 8说:

Names not covered by these rules have no linkage. 这些规则未涵盖的名称没有关联。 Moreover, except as noted, a name declared in a local scope (3.3.2) has no linkage. 此外,除另有说明外,在本地范围(3.3.2)中声明的名称没有链接。

Members of local classes are not covered there. 本地课程的成员不在此处。 §9.3/3 clarifies that: 第9.3 / 3节阐明:

Member functions of a local class (9.8) have no linkage. 本地类的成员函数(9.8)没有链接。

Long story cut short: don't use member functions of a local class as callbacks, use a non-local class instead. 长话短说:不要将本地类的成员函数用作回调,而应使用非本地类。

You fist variant is the correct one as long as the specific matter of taking the address is considered. 只要考虑到地址的特定问题,您的拳头变体就是正确的选择。 There are no restrictions on taking the address of member functions of local classes. 对采用本地类的成员函数的地址没有任何限制。 The proper syntax is the usual 正确的语法是通常的

&NestedClass::someFunction

ans that's it. 就是这样。 You can try saving it in an intermediate pointer in your code 您可以尝试将其保存在代码的中间指针中

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

and I'm sure your compiler will accept it. 并且我确定您的编译器会接受它。

However, the problem I suspect exists in your code has absolutely nothing to do with the proper way of taking the address of a member function. 但是,我怀疑代码中存在的问题与获取成员函数的地址的正确方法完全无关。 It is rather about the way the first parameter of setupCallback is declared. 而是关于setupCallback的第一个参数的声明方式。 Since you say it works with &SomeClass::someFunction as the first argument, I'd expect setupCallback to be declared as 既然您说它与&SomeClass::someFunction作为第一个参数一起使用,所以我希望setupCallback被声明为

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

ie it is hardcoded to expect a pointer to a member of SomeClass specifically. 即, 硬编码期望有一个指向SomeClass成员的指针。 You cannot supply a pointer to a member of NestedClass instead. 您不能提供指向NestedClass成员的指针。 NestedClass is completely unrelated to SomeClass and pointers to members of NestedClass are completely incompatible with pointers to members of SomeClass . NestedClassSomeClass完全无关,指向NestedClass成员的指针与指向SomeClass成员的指针完全不兼容。 This is why it won't compile. 这就是为什么它不会编译的原因。

Unless there's something you are not showing us (like setupCallback being a function template maybe? Or overloaded for different parameter types?), what you are trying to do is simply impossible to achieve regardless of how you take the member address, as long as NestedClass remains unrelated to SomeClass . 除非您没有向我们展示某些东西(例如setupCallback可能是一个函数模板?或者是否为不同的参数类型重载了?),否则无论您如何获取成员地址,只要NestedClass ,您将无法实现的NestedClass仍然与SomeClass无关。 Function setupCallback is designed to work with SomeClass and SomeClass only. 函数setupCallback旨在仅与SomeClassSomeClass使用。

Provide more information about setupCallback . 提供有关setupCallback更多信息。 How is it declared? 怎么声明的?

Note that if the setupCallback is declared as a function template parametrized by class type, as in 请注意,如果将setupCallback声明为按类类型参数化的函数模板,如

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

then you won't be able to use the local class NestedClass as template argument for parameter T . 那么您将无法使用本地类NestedClass作为参数T模板参数。 In this case the fact that your NestedClass has no linkage does indeed come into play. 在这种情况下,您的NestedClass没有链接的事实确实起作用。 But, again, it has nothing to do with taking the member address, but rather caused by the fact that classes with no linkage cannot be used as template arguments in C++. 但是,再次,它与获取成员地址无关,而是由以下事实引起的:没有链接的类不能用作C ++中的模板参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM