使用“using”关键字获取类方法的指针

4

我正在使用 Visual Studio 2010。

为什么我无法获取指向在子类中“升级”为公共的类方法的指针?

以下代码无法编译:

#include <iostream>
#include <functional>

class Parent {
protected:
    void foo() {
        std::cout << "Parent::foo()\n";
    }
};

class Child : public Parent
{
public:
    //void foo() { Parent::foo(); } //This compiles
    using Parent::foo; //This does NOT compile
};
int main() {
    Child c;

    std::function < void () > f = std::bind(&Child::foo, &c);
    f();
    return 0;
}

它会出现错误:
error C2248: 'Parent::foo' : cannot access protected member declared in class 'Parent'

它们是不同的方法。使用Parent::foo作为Child::foo的别名,而public关键字使任何人都可以访问该别名:它对Parent::foo没有任何改变。 - IdeaHat
1
不知道问题出在哪里,但也许可以使用本十年内构建的兼容编译器?[点击此处查看实时演示]。你说你正在使用VS2010,也许升级到2012版本(带有2012年11月CTP)或适当的gcc或clang(但如果你是VS用户,那不太可能)。 - WhozCraig
当移除行 std::function < void () > f = std::bind(&Child::foo, &c); 时,代码在 TDM-GCC (MINGW) 4.7.1 下编译正常(错误:function 不是 std 的成员)。 - Lorenzo Donati support Ukraine
1
似乎是微软编译器中的一个错误,或者是一些在C++标准中没有完全覆盖的特殊情况。看起来他们将“using”公开的方法仅视为别名。请参阅此线程:https://groups.google.com/d/msg/comp.lang.c++/9gc84gCrkvw/AQw1Zv2-LKIJ - e.tadeu
4个回答

3

它可以在这里编译通过。

我认为你只是忘了在编译器中添加C++11选项。

例如,对于gcc来说,是-std=c++11或者-std=gnu++11

编辑:这里看起来,在任何Visual Studio版本中都没有实现使用别名声明

事实上,这里有些人谈到了一个编译器的错误

奇怪的是:

c.foo();                                                   // this works fine
std::function < void () > f = std::bind(&Child::foo, &c);  // this won't compile

我正在使用Visual Studio 2010。我也在Visual Studio 2013和Visual Studio 2012上进行了测试,但没有成功。 - Gustavo Muenz
的确。使用TDM-GCC(MINGW)4.7.1和-std=c++11编译没有问题。 - Lorenzo Donati support Ukraine
1
@EdisonGustavoMuenz 正如我的编辑所说,似乎在Visual Studio中尚未实现使用别名声明的功能。 - Pierre Fourgeaud
该链接仅涉及到 using 类型别名,这是 C++11 的一个特性。foo 不是一种类型,而是一个函数,因此 OP 中的 using 声明是普通的 C++98 声明。 - Oktalist
@Oktalist,他们在这里讨论编译器中的一个错误。链接 - Pierre Fourgeaud

1
由于某些原因,Visual Studio不允许您获取foo的地址,即使它是使用普通的C++03语法声明的Child的公共成员。
std::function<void()> f = std::bind(&Child::foo, &c); // won't compile

auto fp = &Child::foo; // also won't compile

直接调用函数仍然正常工作:
c.foo(); // compiles OK

有趣的是,这意味着你可以利用VS2010的部分C++11支持来解决其C++03支持中的缺陷,通过使用lambda表达式来实现与您的bind表达式相同的效果:

std::function<void()> f = [&c]{ c.foo(); }; // compiles OK!

0
这段代码可以使用 g++ 4.8.1 进行编译。您是否正在使用 C++11?运行时,我得到了以下输出结果:
Parent::foo()

我正在使用Visual Studio 2010。 我也在Visual Studio 2013和Visual Studio 2012上进行了测试,但没有成功。 - Gustavo Muenz

0
在 C++11 之前,这个 'using' 允许在这种情况下不隐藏 Parent::foo:
class Parent
{
protected:
    void foo() {}
};

class Child : public Parent
{
    using Parent::foo; // without this, following code doesn't compile.
public:
    // foo(int) hides Parent::foo without the 'using'
    void foo(int) { return foo(); }
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接