为什么调用非 const 成员函数而不是 const 成员函数?

发布于 2024-12-02 11:15:26 字数 965 浏览 1 评论 0原文

为了我的目的,我尝试包装一些类似于 Qt 共享数据指针的东西,经过测试,我发现当应该调用 const 函数时,会选择它的非 const 版本。

我使用 C++0x 选项进行编译,这是一个最小的代码:

struct Data {
    int x() const {
        return 1;
    }
};

template <class T>
struct container
{
    container() {
        ptr = new T();
    }


    T & operator*() {
        puts("non const data ptr");
        return *ptr;
    }

    T * operator->() {
        puts("non const data ptr");
        return ptr;
    }

    const T & operator*() const {
        puts("const data ptr");
        return *ptr;
    }

    const T * operator->() const {
        puts("const data ptr");
        return ptr;
    }

    T* ptr;
};

typedef container<Data> testType;

void testing() {
    testType test;
    test->x();
}

如您所见,Data.x 是一个 const 函数,因此运算符 ->被调用的应该是 cons 。当我注释掉非常量时,它编译时没有错误,所以这是可能的。然而我的终端打印:

“非常量数据指针”

这是一个 GCC bug(我有 4.5.2),还是我遗漏了什么?

I tried to wrap something similar to Qt's shared data pointers for my purposes, and upon testing I found out that when the const function should be called, its non-const version was chosen instead.

I'm compiling with C++0x options, and here is a minimal code:

struct Data {
    int x() const {
        return 1;
    }
};

template <class T>
struct container
{
    container() {
        ptr = new T();
    }


    T & operator*() {
        puts("non const data ptr");
        return *ptr;
    }

    T * operator->() {
        puts("non const data ptr");
        return ptr;
    }

    const T & operator*() const {
        puts("const data ptr");
        return *ptr;
    }

    const T * operator->() const {
        puts("const data ptr");
        return ptr;
    }

    T* ptr;
};

typedef container<Data> testType;

void testing() {
    testType test;
    test->x();
}

As you can see, Data.x is a const function, so the operator -> called should be the const one. And when I comment out the non-const one, it compiles without errors, so it's possible. Yet my terminal prints:

"non const data ptr"

Is it a GCC bug (I have 4.5.2), or is there something I'm missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

掀纱窥君容 2024-12-09 11:15:26

如果您有两个仅在 const 性质上有所不同的重载,则编译器会根据 *this 是否为 const 来解析调用。在您的示例代码中,test 不是const,因此调用非const 重载。

如果您这样做:

testType test;
const testType &test2 = test;
test2->x();

您应该看到另一个重载被调用,因为 test2const

If you have two overloads that differ only in their const-ness, then the compiler resolves the call based on whether *this is const or not. In your example code, test is not const, so the non-const overload is called.

If you did this:

testType test;
const testType &test2 = test;
test2->x();

you should see that the other overload gets called, because test2 is const.

ゝ杯具 2024-12-09 11:15:26

test 是一个非常量对象,因此编译器会找到最佳匹配:非常量版本。不过,您可以使用 static_cast 应用常量: static_cast(test)->x();

编辑:顺便说一句,正如您怀疑的 99.9%当您认为发现了编译器错误时,您应该重新访问代码,因为可能存在一些奇怪的怪癖,而编译器实际上遵循标准。

test is a non-const object, so the compiler finds the best match: The non-const version. You can apply constness with static_cast though: static_cast<const testType&>(test)->x();

EDIT: As an aside, as you suspected 99.9% of the time you think you've found a compiler bug you should revisit your code as there's probably some weird quirk and the compiler is in fact following the standard.

趁微风不噪 2024-12-09 11:15:26

Data::x 是否是常量函数并不重要。被调用的运算符属于container类而不是Data类,并且其实例不是常量,因此调用非常量运算符。如果只有常量运算符可用或者类的实例本身就是常量,则将调用常量运算符。

It doesn't matter whether Data::x is a constant function or not. The operator being called belongs to container<Data> class and not Data class, and its instance is not constant, so non-constant operator is called. If there was only constant operator available or the instance of the class was constant itself, then constant operator would have been called.

断肠人 2024-12-09 11:15:26

但 testType 不是 const 对象。

因此它将调用其成员的非常量版本。
如果这些方法具有完全相同的参数,则必须选择调用哪个版本(因此它使用 this 参数(隐藏的参数))。在本例中,这不是 const,因此您将获得非常量方法。

testType const test2;
test2->x();  // This will call the const version

这不会影响对 x() 的调用,因为您可以在非 const 对象上调用 const 方法。

But testType is not a const object.

Thus it will call the non const version of its members.
If the methods have exactly the same parameters it has to make a choice on which version to call (so it uses the this parameter (the hidden one)). In this case this is not const so you get the non-const method.

testType const test2;
test2->x();  // This will call the const version

This does not affect the call to x() as you can call a const method on a non const object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文