【问题标题】:How to get address of member function for local class defined in function (C++)如何获取函数中定义的本地类的成员函数地址(C++)
【发布时间】:2010-01-28 07:05:05
【问题描述】:

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

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,它不知道我要做什么。 尝试 #1 会生成一条更有用的错误消息,指出不存在 setupCallback,其形式为“setupCallback(void (SomeUnitTest::someTest()::NestedClass::SomeFunction::*), etc) 尝试#3 就是这样诞生的。

我真的找不到很多关于在函数中定义的类的信息,有谁知道正确的语法,也许有讨论这个主题的资源?

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

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

【问题讨论】:

  • 我很确定你一开始就不能在 C++ 的函数中定义一个类。
  • @Max S:不,你可以(毕竟classstruct 等价)。顺便说一句,“嵌套类”通常是指另一个类中的一个类。
  • @Max. S:这些被称为本地类,并在标准中明确提及——尽管与非本地类相比,它们有些残缺。
  • 你需要告诉我们更多关于setupCalback函数的信息。它是如何声明的?它期望什么参数类型?您的代码中的问题与地址本身或本地类有关。问题是setupCallbak 调用中的参数与参数不兼容。这就是编译器实际上试图告诉你的。

标签: c++ member-function-pointers local-class


【解决方案1】:

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

§3.5/8 说:

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

那里不包括本地班级的成员。 §9.3/3 阐明:

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

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

【讨论】:

  • 在函数中定义一个类在过去是很多麻烦的根源,所以我什至不再考虑它们,因为我总是忘记一些陷阱。
  • 本地类没有链接这一事实绝不意味着您不能创建指向其成员的指针。就像自动变量没有链接这一事实并不能阻止我们创建指向此类变量的指针。
  • 链接在这里发挥作用的唯一方法是setupCallback 实际上是一个由类类型参数化的函数模板。没有链接的类不能用作 C++ 中的模板参数(有关详细信息,请参阅我的答案)。
  • 我可能说得更清楚了,但我并不是要暗示你不能接受本地班级成员的地址。我只是指出,抛开语法问题不谈,由于没有链接,它无论如何都行不通。如果它无论如何都不能工作,为什么还要为语法问题烦恼?
  • @gf:为什么它不起作用?在这种情况下,您认为 linkage 有什么重要性?获取地址并通过链接的指针不管调用类的成员绝对没有问题(包括将其用作回调)。同样,如果涉及模板,我可以猜测“无链接”的唯一潜在问题是模板参数可能存在的问题。
【解决方案2】:

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

&NestedClass::someFunction

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

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

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

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

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

硬编码特别期望指向SomeClass 成员的指针。您不能改为提供指向NestedClass 成员的指针。 NestedClassSomeClass 完全无关,指向NestedClass 成员的指针与指向SomeClass 成员的指针完全不兼容。这就是它无法编译的原因。

除非您没有向我们展示某些内容(例如 setupCallback 可能是一个函数模板?或者为不同的参数类型重载?),否则无论您如何获取成员地址,您都无法实现,只要NestedClassSomeClass 保持无关。函数 setupCallback 仅适用于 SomeClassSomeClass

提供有关setupCallback 的更多信息。它是如何声明的?

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

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

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

【讨论】:

  • 我更新了问题。我认为本地类没有链接的事实确实是这里的问题?
  • @czuger:更新后的代码仍然有点脏(不可编译),但通常是的,本地类没有链接这一事实使其无法用作模板参数。语言规范明确说明了这一点。这就是问题的根源。至于取地址:没有问题。您的“Try #1”变体使用正确的语法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-28
  • 2013-11-22
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多