Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent const class function from calling non-const class function on reference member

Excuse me for the pretty obscure title, but it does kinda say it all. This is what I mean

class A
{
    void DoSomething(); // non-const
}
Class B
{
public:
    B(A& a) : _a(a) { }
    // const function
    void DoSomethingElse() const
    {
        // Is there a way to disallow this?
        _a.DoSomething();
    }
    void DoEvenMore()
    {
        // Should be OK
        _a.DoSomething();
    }
private:
    // Can't make it const A& because it needs
    // be non-const for non-const functions
    A& _a; // A reference
}

So is there a way I can prevent B::DoSomethingElse() from calling A::DoSomething()?
However, B::DoEventMore() which is not const should be able to keep on calling.

I'm using Visual C++ 2013.

The code above would demonstrate a bug in my program. (In my scenario class A would unload the calling code's object/this pointer.) Since the point of const-correctness would be to prevent these kind of errors, I was just wondering if there's a way to check for this at compile time.

In the application I'm writing the function wouldn't seem dangerous to call at all. When calling it from DoEvenMore() the result would be the same, except that the destruction of B is deferred until the function is done running.

like image 487
Aidiakapi Avatar asked May 12 '14 23:05

Aidiakapi


People also ask

Can a const member function call a non-const member function?

const member functions may be invoked for const and non-const objects. non-const member functions can only be invoked for non-const objects. If a non-const member function is invoked on a const object, it is a compiler error.

What will happen if a const object calls a non-const member function?

Since we can't call non-const member functions on const objects, this will cause a compile error.

Can a const reference be assigned to a non-const reference?

No. A reference is simply an alias for an existing object. const is enforced by the compiler; it simply checks that you don't attempt to modify the object through the reference r .

Can a const function return a non-const reference?

If the thing you are returning by reference is logically part of your this object, independent of whether it is physically embedded within your this object, then a const method needs to return by const reference or by value, but not by non-const reference.


2 Answers

Instead of using the _a data member directly create accessor functions with const and non-const overloads. This will cause the const overload to be selected when called from within const member functions of B, which in turn prevents you from calling non-const functions of A.

A const& GetA() const { return _a; }
A& GetA() { return _a; }


void DoSomethingElse() const
{
    GetA().DoSomething(); // error
}
like image 174
Praetorian Avatar answered Sep 21 '22 05:09

Praetorian


The rules for "constness" make the object itself immutable but does not affect the constness of pointed to/referred objects. If you want to access a const reference only when you use a const method, you need to create a method overloaded on constness that returns either a reference or a const reference.

class B {
private:
    inline A& a() { return _a; }
    inline const A& a() const { return _a; }
public:
    // ...
};
like image 45
zneak Avatar answered Sep 21 '22 05:09

zneak