public const doesn't override private const function? - c++

I have a class with a header like this:
public:
const dtMeshTile* getTile(int i) const;
private:
dtMeshTile* getTile(int i);
When I try to use it like this:
const dtMeshTile* const tile = navmesh->getTile(i);
I'm getting a "'dtMeshTile* getTile(int)' is private within this context" How can I specify the public function?

Consider:
#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();
}
At the point of the call: const Bar& ref = foo.get(); you might expect the const version of get() to be called, because you are assigning a const reference.
But this is not the case. Return types are not a part of a function's (or method's) signature, so when the compiler is looking for which function to call in a list of possible overloads, the return type is not considered. (In fact, the Standard rejects function overloads which differ only by return type.)
So, how does the compiler decide which function to call? By looking at the information is does have available to it. The tweo overloads are identical in terms of parameters (both are void), so the only thing it has to go on is the static type of the object used to make the call: foo. That static type in this case is Foo -- decidedly non-const.
Therefore it tried to call the only function it can: the non-const version of get(). Which of course won't compile because that is private.
In order to fox this, the static type can be changed to be a const Foo (or something similar), like this:
Foo foo (bar);
Bar& ref = foo.get();
Or maybe...
Foo foo (bar);
const Bar& ref = static_cast <const Foo&> (foo).get();
But in practice, I would rather advise that the names of these functions be unambigious, rather that relying on such "tricks" to contort the compiler in to doing what you want.

make sure navmesh is const in the context of your call. But I would not recommend const_cast it, you might read this http://www.parashift.com/c++-faq/overview-const.html .

You're hit by a pretty common design flow -- an overload set with mixed semantics.
But I guess you can't change the class, only work around it.
Your problem comes from overload resolution rules. The function is selected based on arguments. Only. private/public stuff is ignored at this stage. The selection happens based on the type before -> if if it's const T*, the first function is selected, for T* the second.
Assess check is applied then, so for the latter case you get the error report. To force the desired function you must use a cast, or better create a free wrapper function
const dtMeshTile* getXXXTile(const XXX* p, int i) {return p->getTitle(i);}
(or a ref-taking variant).
In my codebase the second function would have a different name, as obtaining a mutable string is way different in semantics.

Related

Const references sometimes lead to confusion

I'm new to C++. I learned that references should be used whenever possible and that pointers should be used only when strictly necessary. I also learned that const references should be used in function parameters when the function does not change the referred variable.
I understand the reasons and agree with them, but there's a common case where const references lead to confusion which is when a mutable object "becomes immutable" as an effect (const-ness) of declaring a const reference to an object. For example, the Foo class has a method named incrementX() which mutate the state of Foo when called:
class Foo {
public:
void incrementX();
private:
private int x;
}
void Foo::incrementX() {
x++;
}
class Bar {
public:
void doSomethingWith(const Foo &foo);
}
void Bar::doSomethingWith(const Foo &foo) {
foo.incrementX(); // <- illegal because incrementX() is not a const method
}
int main() {
Foo foo;
Bar bar;
bar.doSomethingWith(foo);
}
The usual solution is to declare incrementX() as a const method, which in turn forces me to declare the variable x as a mutable variable. The problem is, by turning incrementX() into a const method I'm saying that this method is not supposed to mutate the object's state, which is not true in the above example. Not only it's not true, it's also the method's intent to mutate the object's state.
I'm curious how experienced C++ programmers deal with this situation. I'm inclined to use const pointers (Foo * const foo) in such cases, would that be recommended/discourage?
Thanks.
EDIT: Just to clarify the cause of my confusion, I often hear people saying "use const refs when the function promises not to change the parameter", but what exactly "to change the parameter" means? Does it mean the function promises not to assign a new object to the parameter, or does it mean it will not mutate the objects's state? Of course, const references disallow both kind of changes, but what's the main concern when it comes to const references? Is it that it will not assign a new value to the parameter, or is it that it will not mutate the state of the object referred to by the const reference?
By taking const Foo &
void Bar::doSomethingWith(const Foo &foo)
promises not to modify the foo. Therefore it may not call it's non-const incrementX method.
If you have Bar::doSomethingWith(Foo &foo) that needs to call foo.incrementX (and therefore needs to take it's argument non-const reference), than you should reconsider whether it is really appropriate to be a method of Bar and not Foo in the first place.
Do not pass by const reference if you expect that your object will be changed, or overload the function so that you have doSomethingWith(const Foo&) and doSomethingWith(Foo&).
The whole idea is that passing by const reference forces const behaviour, so you can only invoke member functions that are marked const, and this leads to less problems in the long run.
PS: I made the doSomething a member of Foo.
Example:
#include <iostream>
using namespace std;
class Foo
{
int m=0;
public:
void doSomething(const Foo& foo) const
{
cout << "calling const reference" << endl;
}
void doSomething(Foo& foo)
{
cout << "calling reference" << endl;
foo.m++;
}
};
int main()
{
const Foo f,g ;
f.doSomething(g); // calls const reference
Foo h,k;
h.doSomething(k); // calls reference
}

C++ facade avoiding copies

Consider the following, simplified facade pattern:
class Foo {
public:
int times;
int eval(const int val) { return val*times; }
};
class Bar {
Foo foo;
public:
Bar(const Foo& f) : foo(f) {}
double eval(const double val) { return val * foo.times; }
};
Obviously, an instance of Bar is only required to evaluate a special (i.e. double-valued) interpretation of Foo's eval() method. A Bar won't have any other members except the foo it forwards to.
For safety reasons I have not used a const reference or a pointer inside Bar (I just don't know yet if at some point a Bar instance might escape from a stack frame, so resource management is important).
My question here is two fold:
Can the C++ compiler possibly detect that Bar is merely a facade and
"inline" the member access?
Is there a (safe) way to prevent copying
of the passed object?
On some platforms (gcc/clang) you can force inlining with the attribute always_inline or emit warnings should a function not be inlined.
No, if you don't want to copy, you need to guarantee the life-time of the object elsewhere. If you consider this to be unsafe, don't do it. What you can do is move an object. This avoids copies and life-time issues, but might not be possible with your compiler.
For example:
struct Bar {
// Only accept rvalues of Foo
explicit Bar(Foo&& f) : f(std::move(f)) {}
Foo f;
};
1- Yes, the compiler will most probably inline the function [It depends on compiler).
2- Always stick to RAII. In C++3, Foo object foo shall be either member variable (as you did), or managed pointer (copied at copy constructor and assignment operator and deleted at destructor). In C++11 you can use right value reference.
NOTE: This example is not a facade!

Cast const member function to non-const

Is casting the constness of member function pointers defined in C++? Is the following valid code?
struct T {
void foo(int i) const { std::cout << i << std::endl;};
};
void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int) = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1);
Update:
The reason why I need this is that I'm writing a function that accepts both an object and a member function pointer to that object. I need a version for const objects (accepting only const functions) and a normal one. Since I don't want duplicate code, my idea was to put the actual code in the non-const version and call it from the const one, casting away any consts.
Compiler eats it.
But the backward cast is more useful.
And again but - it is better to don't use it, const_cast is usually just a quick and dirty solution, which you apply only when there are not any other solution.
Answer to update
If I understand you correctly you are going to use one object and two function. First function accepts const object and const member-function, second - non-const object and non-const member-function.
According to given information you can change second function to accept non-const object and const member-function. And give them one non-const object and its const member-function.
Yes, it is defined, but you maybe don't want it if the function is really const, because some compiler optimizations (namely return value caching) depend on the function being const.
You can do it, but it has no meaning, wherever you can call f2, you can also call f1 too. You should cast in the other way. But if something, you should cast the object, not the function.
void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int) = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1); // compiles
(t.*f1)(1); // this compiles too!!
but if you have
const T t;
(t.*f2)(1); // error t is const
(t.*f1)(1); // still compiles
The only was to resolve the ambiguity is to perform a static_cast, this is basically a language feature
#include <boost/typeof/typeof.hpp>
struct Test
{
const int& foo();
const int& foo() const;
};
int main()
{
typedef const int&(Test::*non_const_ptr)();
typedef const int&(Test::*const_ptr)()const;
BOOST_TYPEOF(static_cast<non_const_ptr>(&Test::foo)) ss;
}
I don't see a reason for doing this: even if you could, you'd make it more restrictive.
Let's say you have a class Foo:
class Foo {
void f() const;
void g();
}
And some snippet of code:
Foo a;
const Foo b;
Then you can call both a.f() and a.g(), but not b.g() because b is const. As you can see, placing const after a member function makes it less restrictive, not more.
And, by reinterpret_casting this pointer, you'll get the pointer with exact same value(due to the nature of reinterpret_cast), and if you try to call it, you'll get into the same T::foo()

Why can't I access a public function that has a protected overload?

Given the code:
class Foo
{
public:
Foo() {}
int foo() const { return 6; }
protected:
int foo() { return 5; }
};
int main(int argc, char* argv[])
{
Foo foo;
foo.foo();
return 0;
}
I get a compile error:
'Foo::foo' : cannot access protected member declared in class 'Foo'
In actual usage, I'm trying to provide a function that returns a pointer to an object that the class is storing - modifiable for the members, and const for everyone else. I figured that if I say
const Item *i = foo.foo();
in a non-member function, the correct, const variant will be called. Somehow though, the compiler insists on accessing the non-const variant in the protected section. Any idea why? Thanks.
Your variable is non-const, so the non-const overload of the function is selected. After overload resolution occurs, then accessibility is checked.
When const and non-const functions both exist, the const version is only called on const objects. Your foo variable is not const. You can make it const with a const_cast if you want:
const_cast<Foo const&>(foo).foo();
That's cumbersome to use, though. A better solution would be to just give the internal function a different name so it doesn't clash with the external API.
For a non-const object, non-const function overload is chosen over the const function, if both are existing.
foo is of type Foo and not const Foo, that's why compiler chooses the protected version which is non-const.
In 3 ways the code will compile:
Either, Make Foo::foo() in public
Or, use const Foo, so that compiler chooses the const-correct
version
Remove the non-const version

How to properly return reference to class member?

class Foo {
protected:
QPoint& bar() const;
private:
QPoint m_bar;
};
QPoint& Foo::bar() const {
return m_bar;
}
I got this error:
error: invalid initialization of reference of type ‘QPoint&’ from expression of type ‘const QPoint’
However it works if I change it to this:
QPoint& Foo::bar() const {
return (QPoint&) m_bar;
}
1) I don't understand why the compiler says that my QPoint is const.
2) Is it ok to leave the cast there?
In a non-const member function of class Foo the this pointer is of the type Foo* const - that is, the pointer is const, but not the instance it points to. In a const member function, however, the this pointer is of the type const Foo* const. This means that the object it points to is constant, too.
Therefore, in your example, when you use this->m_bar (of which m_bar is just the short form), then m_bar is a member of a constant object - which is why you cannot return it as a non-const reference.
This actually makes sense from a design POV: If that Foo object is a constant object, and you are allowed to invoke Foo::bar for constant objects, then, if this would return a non-const reference to some internals which you can fiddle with, you would be able to change the state of a constant object.
Now you have to look at your design and ask yourself how you arrived at this point and what your actual intention is. If that m_bar member isn't really part of the state of the object (for example, it's only there for debugging purposes), then you could consider making it mutable. If it is part of the state of the object, then you have to ask yourself why you want to return a non-const reference to some internal data of a constant object. Either make the member function non-const, or return a const reference, or overload the member function:
class Foo {
public:
const QPoint& bar() const {return m_bar;}
QPoint& bar() {return m_bar;}
// ...
};
What you're trying to do is a no-no. You do not want to return a QPoint & from your bar function as this breaks encapsulation because a caller can now modify m_bar out from underneath QPoint. (luckily you have the function declared as const or you wouldn't get an error here and you would still be breaking encapsulation).
What you want in this case is
const QPoint &Foo::bar() const
{
return m_bar;
}
Edit based on user comment:
IMHO, this would be better solved by adding a setX to Foo instead of calling a non-const function from a non-const reference returned by an accessor function that should really be const. Overloading the accessor function to remove the const just puts a band-aid over the real problem and just hides the fact that encapsulation is compromised. Adding setX to Foo fixes the encapsulation problem and also plugs the leaking interface you are creating by returning a non-const reference to private data.
For example, if you put foo.bar().setX(100); in many parts of your application and later change the type of QPoint to one that doesn't implement setX or simply rename the function setX to say setPointX you have problems b/c you now have to go around a rename/refactor all of these calls. Creating a setX on Foo makes the code easier to call foo.setX(100) vs foo.bar().setX(100), is const correct, and encapsulates your data. If you changed QPoint to be just 2 x and y coordinates in Foo, nothing outside of your class would have to change b/c you have good encapsulation.
The const on the function tells the compiler that the function doesnt modify any member variables. However, since your returning a reference to the member variable it cant guarantee that any more and thus has the compile error.
The compiler is not expecting your member variable to be const but the return from the function to be const. Remove the const from the function def.
either use
const QPoint& Foo::bar() const {
return m_bar;
}
or
QPoint& Foo::bar() {
return m_bar;
}
I guess you could also declare m_bar as:
mutable QPoint m_bar;
EDIT: mutable defense
#tstenner:
mutable has its place. It is not 'evil' definitely no more so than void* or casting. Assume something like the following:
class foo {
SomeType bar;
public:
foo() : bar() { }
const SomeType& bar() const { return a; }
};
In this case, bar is ALWAYS constructed, even if bar() is never called. This may be fine, but if SomeType has a costly constructor, it can be preferable to allow lazy instantiation of bar.
Consider:
class foo2 {
mutable SomeType* bar;
mutable bool cached;
public:
foo2() : bar(0), cached(false) { }
const SomeType& bar() const {
if( ! cached ) {
cached = true;
bar = new SomeType();
}
return *bar;
}
};
This allows foo2 to mimic a non-lazy instantiated class, while being lazily instantiated. Granted, the mutability of foo2 has implications for thread safety, but these can be overcome with locking if needed.
If it allowed you to return a reference to the variable, then you could modify a const instance of Foo class. Consider such code:
void baz(const Foo &foo)
{
QPoint &ref = foo.bar(); //if it was allowed...
ref = 5; // ...you could have modified a const object foo!
}
Therefore compiler prevents you from doing that.
You should either declare your method returning const QPoint& or to revise your understanding of what really const is for.
Someone may advise you to use mutable. Don't. mutable keyword is to allow implementation of the class to modify internal member variables of const objects (for example, for memoization purposes), rather than to expose non-const variable (!) to external code.