如何从 const 方法调用非常量方法?

发布于 2024-12-18 21:28:15 字数 327 浏览 2 评论 0原文

我的类中有一个 const 方法,无法将其更改为非常量。在这个方法中,我需要调用一个非常量方法,但编译器不允许我这样做。

有什么办法解决吗?这是我的代码的简化示例:

int SomeClass::someMethod() const {
    QColor saveColor = color();
    setColor(QColor(255,255,255)); // Calling non-const method

    // ....

    setColor(saveColor); // restore color

    return 1;
}

I've got a const method in my class, which cannot be changed to non-const. In this method, I need to call a non-const method but the compiler doesn't let me do that.

Is there any way around it? Here is a simplified sample of my code:

int SomeClass::someMethod() const {
    QColor saveColor = color();
    setColor(QColor(255,255,255)); // Calling non-const method

    // ....

    setColor(saveColor); // restore color

    return 1;
}

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

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

发布评论

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

评论(4

我还不会笑 2024-12-25 21:28:15

您可以在 this 指针上使用 const_cast

int SomeClass::someMethod() const {
    const_cast<SomeClass*>( this )->setColor(...);// Calling non-const method
    //whatever
}

但如果您对最初声明为 const 的对象执行此操作,则会遇到未定义的行为。

所以 this:

SomeClass object;
object.someMethod();

没问题,但是 this:

const SomeClass object;
object.someMethod();

会产生未定义的行为。

真正的解决方案是,您的 const 函数首先就不应该是 const

You could use const_cast on this pointer,

int SomeClass::someMethod() const {
    const_cast<SomeClass*>( this )->setColor(...);// Calling non-const method
    //whatever
}

but if you do that for an object that was originally declared const you run into undefined behavior.

So this:

SomeClass object;
object.someMethod();

is okay, but this:

const SomeClass object;
object.someMethod();

yields undefined behavior.

The real solution is that your const function should not be const in the first place.

不喜欢何必死缠烂打 2024-12-25 21:28:15

实现 const 正确性的挑战之一是不能半途而废。要么全有,要么全无。如果你试图半途而废,你最终会陷入像现在这样的困境。你最终会得到一个很好的 const 正确的类,被一些疯狂的旧的、通常是遗留的(或由老脾气暴躁的人编写的)代码使用,而这些代码不是 const 正确的,并且它就是行不通。您会想知道 const 的正确性是否值得所有的麻烦。

我需要[从 const 方法] 调用非常量方法

你不能——不能直接调用。你也不应该。但是,还有另一种选择......

显然,您不能从 const 方法调用非 const 方法。否则,const 在应用于成员函数时将没有任何意义。

const 成员函数可以更改标记为 mutable 的成员变量,但您已指出这在您的情况下是不可能的。

您可以尝试通过执行诸如 SomeClass* me = const_cast(this); 之类的操作来摆脱 const 性,但是 A) 这通常会导致 UB,或者 2) 它违反了 const 正确性的整个理念。

如果您真正想要实现的目标能够支持这一点,您可以做的一件事是创建一个非 const 代理对象,并执行非 const-y 的操作与此。也就是说:

#include <iostream>
#include <string>
using namespace std;

class Gizmo
{
public:
    Gizmo() : n_(42) {};
    void Foo() const;
    void Bar() { cout << "Bar() : " << n_ << "\n"; }
    void SetN(int n) { n_ = n; };
    int GetN() const { return n_; }
private:
    int n_;
};

void Gizmo::Foo() const
{
    // we want to do non-const'y things, so create a proxy...
    Gizmo proxy(*this);
    int save_n = proxy.GetN();
    proxy.SetN(save_n + 1);
    proxy.Bar();
    proxy.SetN(save_n);
}

int main()
{
    Gizmo gizmo;
    gizmo.Foo();
}

One of the challenges of doing const-correctness is you can't do it halfway. It's either all or nothing. If you try to do it halfway, you end up in a tough spot like you are here. You end up with a nice const-correct class being used by some crazy old, typically legacy (or written by an old curmudgeon) code that isn't const-correct and it just doesn't work. You're left wondering if const-correctness is worth all the trouble.

I need to call a non-const method [from a const method]

You can't -- not directly. Nor should you. However, there is an alternative...

Obviously you can't call a non-const method from a const method. Otherwise, const would have no meaning when applied to member functions.

A const member function can change member variables marked mutable, but you've indicated that this is not possible in your case.

You could attempt to cast away constness by doing something like SomeClass* me = const_cast<SomeClass*>(this); but A) This will typically result in UB, or 2) It violates the whole idea of const-correctness.

One thing you could do, if what you're really trying to accomplish would support this, is to create a non-const proxy object, and do nonconst-y stuff with that. To wit:

#include <iostream>
#include <string>
using namespace std;

class Gizmo
{
public:
    Gizmo() : n_(42) {};
    void Foo() const;
    void Bar() { cout << "Bar() : " << n_ << "\n"; }
    void SetN(int n) { n_ = n; };
    int GetN() const { return n_; }
private:
    int n_;
};

void Gizmo::Foo() const
{
    // we want to do non-const'y things, so create a proxy...
    Gizmo proxy(*this);
    int save_n = proxy.GetN();
    proxy.SetN(save_n + 1);
    proxy.Bar();
    proxy.SetN(save_n);
}

int main()
{
    Gizmo gizmo;
    gizmo.Foo();
}
飘然心甜 2024-12-25 21:28:15

如果您需要更改 const 方法内的某些内部状态,您还可以声明受影响的状态 mutable

class Foo {
public:
    void doStuff() const { bar = 5; }
private:
    mutable int bar;
};

这适用于将互斥体等内容作为以下成员的情况你的班级。获取和释放互斥锁不会影响客户端可见状态,但从技术上讲,在 const 方法中是被禁止的。解决方案是将互斥体标记为可变。您的案例看起来很相似,尽管我认为您的课程需要进行一些重构才能适用该解决方案。

另外,您可能需要阅读此答案,了解如何使用 RAII 使此临时状态更改异常安全。

If you require to change some internal state inside a const-method you can also declare the affected state mutable:

class Foo {
public:
    void doStuff() const { bar = 5; }
private:
    mutable int bar;
};

This is intended for cases where you have stuff like mutexes as members of your class. Acquiring and releasing a mutex does not affect client-visible state, but is technically forbidden in a const-method. The solution is to mark the mutex mutable. Your case looks similar, although I think your class requires some refactoring for this solution to be applicable.

Also, you might want to read this answer to see how you can make this temporary state-change exception-safe using RAII.

灯下孤影 2024-12-25 21:28:15

如何从 const 方法调用非常量方法?

你不应该。如果您使用 const_cast 放弃 this 的常量性,则可能会遇到未定义的行为。使用const_cast会让编译器闭嘴,但这不是解决方案。如果您需要这样做,那么这意味着 const 函数首先不应该是 const 。使其成为非常量。

或者,您应该做其他事情,这不需要您从 const 函数调用非常量函数。比如,不调用 setColor 函数?比如,将 const 函数拆分为多个函数(如果可以的话)?还是别的什么?

在您的特定情况下,如果 setColor 仅设置一些成员变量,例如 m_color,那么您可以将其声明为 mutable

 mutable QColor m_color;

然后将其设置在您的const 函数,不调用 setColor 函数,也不执行 const_cast

How to call a non-const method from a const method?

You should not. You might run into undefined behaviour if you cast away the const-ness of this, using const_cast. The usage ofconst_cast will shut the compiler's mouth up, but that isn't a solution. If you need to do, then it means the const function should not be const in the first place. Make it non-const.

Or, you should do something else, which would not require you to call non-const function from const function. Like, don't call setColor function? Like, split the const function into more than one functions (if you can do that)? Or something else?

In your particular case, if setColor only sets some member variable, say m_color, then you can declare it mutable:

 mutable QColor m_color;

and then set it in your const function, without calling setColor function, and without doing const_cast.

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