Why can't I pass a const object in a const argument function/method?
EDIT:
Sorry, I'm trying to understand a sample of code, which uses QList::indexOf
method, declared as in here.
Actually I'm trying to figure out why I need to use const_cast
in this specific case:
int ProjTreeItem::row() const
{
if (parentItem) {
// instance of const object to test
const ProjTreeItem *item = new ProjTreeItem(QList<QVariant>(), NULL);
// Called indexOf here to test
parentItem->childItems.indexOf(item);
// This works fine
return parentItem->childItems.indexOf(con开发者_Go百科st_cast<ProjTreeItem*>(this));
}
return 0;
}
EDIT2:
I was looking at the wrong places, then I started to suspect that the issue had to do with the use of templates and the const
modifier. I found this thread here. Please, look at Jon 's answer, which I think clarifies the point I reached. Sorry for the misleadings on my question.
I think you wanted this instead:
void SomeClass::f(const MyClass*) const
{ ... }
Hmmmm works for me with this code:
class MyClass
{
};
class SomeClass
{
public:
void f(const MyClass *t) const
{
}
};
int main()
{
SomeClass s;
const MyClass *myClass = new MyClass;
MyClass *myClass2 = new MyClass;
s.f(myClass);
s.f(myClass2);
return 0;
}
You are making the wrong assumption that the type of item
is equal to the type of this
, and I believe this is confusing you.
Inside a const
function, the type of this
is ProjTreeItem const * const item
. But your pointer that works is declared const ProjTreeItem * item
:
// `this` is a constant-pointer-to-a-constant-ProjTreeItem
ProjTreeItem const * const this; // obviously not valid code, just illustrating type
// `item` is simply a pointer-to-a-constant-ProjTreeItem
const ProjTreeItem * item;
It helps to read the declaration right to left.
So, declare you item pointer like this and I suspect you'll need a cast as well.
const ProjTreeItem * const item = new ProjTreeItem(QList<QVariant>(), NULL);
I presume you mean the line
parentItem->childItems.indexOf(item);
doesn't compile. I also presume you wrote
QList< ProjTreeItem* > childItems;
in parentItem
's type(class) definition.
If I understand correctly, in the line
parentItem->childItems.indexOf(item)
you are going to convert ProjTreeItem const*
into ProjTreeItem*
, and
this requires const_cast
.
JaredC has already answered kindly about constness.
I suggest reading his answer again carefully.
Edit:
I think Jon's answer applies to your question.
The 1st parameter of QList::indexOf
is T const&
, where T is ProjTreeItem*
in your case.
So, the concrete parameter type is ProjTreeItem*const&
.
Please note it differs from ProjTreeItem const*const&
.
ProjTreeItem*
and ProjTreeItem const*
are different types.
const_cast
is needed to convert from the latter to the former.
ProjTreeItem const*
means that ProjTreeItem
is const
.
However, ProjTreeItem*const&
means pointer is const
, ProjTreeItem
is not const
.
Edit2:
You seem to misunderstand.
#include <typeinfo>
#include <iostream>
using namespace std;
struct ProjTreeItem;
template< class T >
struct Test {
typedef T const type;
};
int main()
{
cout<< boolalpha;
cout<<
(typeid( Test< ProjTreeItem* >::type ) == typeid( ProjTreeItem const* ))
<<endl;
cout<<
(typeid( Test< ProjTreeItem* >::type ) == typeid( ProjTreeItem*const ))
<<endl;
}
If your interpretation is right, the above code will print true
,
and then false
.
However, the code prints false
, and then true
.
精彩评论