公共常量不能覆盖私有常量函数?

5

我有一个带有以下标题的类:

public:
    const dtMeshTile* getTile(int i) const;

private:
    dtMeshTile* getTile(int i);

当我尝试像这样使用它时:

const dtMeshTile* const tile = navmesh->getTile(i);

我遇到了"'dtMeshTile* getTile(int)' is private within this context" 的错误,如何调用公共函数呢?

4
这段代码的意思是,将指向navmesh的const指针赋值给navtmpmesh,并从navmesh中获取第i块tile。 - UldisK
5
const_cast<const ClassType*>(navmesh)->getTile(); 可以翻译为“获取 navmesh 对象的 Tile,去除 const 属性后的类型为 ClassType”。 - BoBTFish
2
如果我没记错的话,编译器选择调用哪个函数是由返回类型决定的(这就是为什么你不能同时拥有int foo(int)和void foo(int))。你尝试过将navmesh强制转换为指向const对象的指针吗?此外,需要使用强制转换来处理选择“正确”函数的事实可能意味着您需要重新设计API。 - user220878
4
导航网格必须是常量才能进行该调用。 - sethi
3个回答

3
考虑以下内容:
#include <cstdlib>

class Bar {}; 
class Foo 
{
public:
    Foo (Bar& bar)
    :   
        mBar (bar)
    {   
    }   
    const Bar& get() const
    {   
        return mBar;
    }   
private:
    Bar& get()
    {   
        return mBar;
    }   

    Bar& mBar;
};

int main()
{
    Bar bar;
    Foo foo (bar);
    Bar& ref = foo.get();
}

在调用点:const Bar& ref = foo.get();,您可能期望调用get()const版本,因为您正在分配一个const引用。
但事实并非如此。返回类型不是函数(或方法)签名的一部分,因此当编译器在可能的重载函数列表中寻找要调用的函数时,不考虑返回类型。(事实上,标准拒绝仅通过返回类型有所不同的函数重载。)
那么,编译器如何决定应该调用哪个函数呢?它通过查看可用的信息来确定。两个重载在参数方面完全相同(都是void),因此它所依据的唯一信息就是用于调用的对象的静态类型:foo。在这种情况下,静态类型是Foo —— 明显是非const类型。
因此,它试图调用唯一可用的函数:非const版本的get()。当然这不会编译,因为它是private的。
为了解决这个问题,可以更改静态类型为const Foo(或类似的类型),像这样:
Foo foo (bar);
Bar& ref = foo.get();

也可能是......
Foo foo (bar);
const Bar& ref = static_cast <const Foo&> (foo).get();

但在实践中,我更建议这些函数的名称应该明确无歧义,而不是依赖这样的“技巧”来扭曲编译器以达到你想要的效果。


非常感谢您提供如此详尽的解释。您涉及到了我所困惑的大部分内容。 - mpellegr

1

你为什么反对在这种情况下使用 const_cast?这也许不是解决整个问题的最佳方案,但它是调用正确函数的合理方式。 - BoBTFish

1
你遇到了一个常见的设计问题——过载集合与混合语义。但我想你无法改变这个类,只能绕着它工作。
你的问题来自于重载解析规则。函数被基于参数选择。在这个阶段,只有 private/public 的内容会被忽略。选择是基于之前的类型进行的,如果是 const T*,那么第一个函数就会被选择,对于 T*,第二个函数会被选择。
然后应用评估检查,所以对于后一种情况,你会得到错误报告。为了强制使用所需的函数,必须使用转换,或者更好地创建一个自由包装函数。
const dtMeshTile* getXXXTile(const XXX* p, int i) {return p->getTitle(i);}

(或者是需要参考的变体)。

在我的代码库中,第二个函数将有一个不同的名称,因为获取可变字符串在语义上有很大的区别。


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