For my compsci class, I am implementing a Stack template class, but have run into an odd error:
Stack.h: In member function ‘const T Stack<T>::top() const [with T = int]’:
Stack.cpp:10: error: passing ‘const Stack<int>’ as ‘this’ argument of ‘void Stack<T>::checkElements() [with T = int]’ discards qualifiers
Stack<T>::top() looks like this:
const T top() const {
checkElements();
return (const T)(first_->data);
}
Stack<T>::checkElements() looks like this:
void checkElements() {
if (first_==NULL || size_==0)
throw range_error("There are no elements in the stack.");
}
The stack uses linked nodes for storage, so first_ is a pointer to the first node.
Why am I getting this error?
Your checkElements() function is not marked as const so you can't call it on const qualified objects.
top(), however is const qualified so in top(), this is a pointer to a const Stack (even if the Stack instance on which top() was called happens to be non-const), so you can't call checkElements() which always requires a non-const instance.
You cannot call a non-const method from a const method. That would 'discard' the const qualifier.
Basically it means that if it allowed you to call the method, then it could change the object, and that would break the promise of not modifying the object that the const at the end of the method signature offers.
You're calling a non-const method from a const method.
Because checkElements() isn't declared const.
void checkElements() const {
if (first_==NULL || size_==0)
throw range_error("There are no elements in the stack.");
}
Without that declaration, checkElements cannot be called on a const object.
Related
I created a const pointer which points to an instance of abject allocated dynamically.I could not understand the object itself is const or not.
Firstly I tried to call a non-const member function by using pointer, as expected it caused a compile error because (it is my explanation, don't know if it is true or not) this pointer created by the member function is assigned to that const pointer. It did not yield anything.
Secondly I tried to dereference the pointer and call that non-const member function. I thought that the this pointer created by member function now will not be a const pointer because compile can not know the object returned by p (namely *p) is returned by a const pointer or not. It turns out that I was mistaken.
How does member-function understand that ?
#include<iostream>
class A
{
int a=4;
public:
A()
{}
void print()
{
std::cout<<a<<std::endl;
}
};
int main()
{
const A* p = new A();
p->print(); //1 causes compile error
(*p).print(); //2 causes compile error
return 0;
}
I thought the line labelled as 2 will not create a compile error.
It causes a compile error.The error message is:
"a.cpp: In function ‘int main()’:
a.cpp:21:13: error: passing ‘const A’ as ‘this’ argument discards qualifiers [-fpermissive]
p->print(); //1 causes compile error
^
a.cpp:10:9: note: in call to ‘void A::print()’
void print()
^~~~~
a.cpp:22:15: error: passing ‘const A’ as ‘this’ argument discards qualifiers [-fpermissive]
(*p).print(); //2 causes compile error
^
a.cpp:10:9: note: in call to ‘void A::print()’
void print()
^~~~~
Variables have types and can therefore be const or non-const, but expressions have types too. The type of (*p) is const A, and you can't call a non-const method of a const type.
There is no difference between (1) and (2). (1) is syntax sugar for (2).
You should define the print method as const in order to call it for const object.
void print() const { ... }
As it has already been noted, expressions have types and the type of (*p) is const A. You cannot call a non-const function on an object of a const type but you can call const member function. Member functions can have a const qualifier which will mark them to be able to be invoked on const objects or pointers to const objects.
void print() const
{
std::cout<<a<<std::endl;
}
This will make your code compile. and it looks like this is what you intended to do anyway.
I have the following variable in QT:
QVector<QVector <int> > buff_d1;
and I need to modify the "inner" vector:
buff_d1.at(i).removeFirst();
buff_d1.at(i).push_back(d1.at(i).at(sample_number));
this is causing the errors:
passing 'const QVector<int>' as 'this' argument of 'void QVector<T>::removeFirst() [with T = int]' discards qualifiers [-fpermissive] buff_d2.at(i).removeFirst();
passing 'const QVector<int>' as 'this' argument of 'void QVector<T>::push_back(const T&) [with T = int]' discards qualifiers [-fpermissive] buff_d1.at(i).push_back(d1.at(i).at(sample_number));
I understand that the "inner" vector is const so I can't modify it, but what is the work around it?
Your at() function returns a const reference:
const T & QVector::at(int i) const
and you're trying to modify this with the removeFirst() function. You should rather use the [] operator to modify it since it provides a non-const returning overload:
T & QVector::operator[](int i)
The same applies for the second error.
at(int index) member function returns an const reference, see the documentation here, so you need to use operator[int index] to return a non const reference to be able to modify it.
I have a very silly question (I think). Its been long time not coding in C++, but I can't figure out this problem.
I have this class:
#include <QList>
class Node {
private:
QList<Node*> _adjacent;
public:
Node();
bool isConnectedTo(Node* n) const;
};
and this implementation for isConnectedTo():
bool Node::isConnectedTo(Node* n) const{
return _adjacent.contains(n) && n->_adjacent.contains(this);
}
and I get the following error in the return line:
Node.cpp: In member function ‘const bool Node::isConnectedTo(Node*) const’:
Node.cpp:25:60: error: invalid conversion from ‘const Node* const’ to ‘Node*’ [-fpermissive]
In file included from /usr/include/qt5/QtCore/QList:1:0,
from Node.hpp:5,
from Node.cpp:1:
/usr/include/qt5/QtCore/qlist.h:913:27: error: initializing argument 1 of ‘bool QList<T>::contains(const T&) const [with T = Node*]’ [-fpermissive]
I think that, since the method is constant, then this is of type const Node* const here.
By reading th Qt doc, I see that QList::contains has the type bool QList::contains(const T & value) const so it should be ok, right? I mean, it takes a const Node*, and a const Node* constis a special case of that, so...
By removing the const at the end of the siganture, it compiles...
Thanks!
Problem is here:
n->_adjacent.contains(this)
Since contains assumes that it will get Node* const and this is type of const Node*. Adding const is not a problem but removing is a problem. So try const_cast like this:
n->_adjacent.contains(const_cast<Node* const>(this))
Inside your "isConnectedTo" function "this pointer" is a const Node * const pointer which means that "this" cant be used to change the contents of the Node object that it refers to.
In your call "n->_adjacent.contains(this)" you are passing "this" pointer to a function which has constant reference parameter (const T& ref where T is Node*). const T& ref where T is Node* means ref is Node* const& i.e a constant reference to a pointer. The constant here refers to the pointer and means that the reference cant be used to alter the pointer. But this does not mean that the reference cant be used to change the object (Node) that the pointer points to. So nothing can stop us from doing something like (*ref).call_to_non_const_function_in_Node.
But "this" pointer in your case points to a constant Node objject. That is why this code doesn't compile. It would have compiled if the parameter were a constant Node* const& i.e constant reference to a pointer to a constant
When you remove const modifier from your member function "this" is just a regular Node* const pointer which is why it compiles.
If you are not planning to change Nodes through the _adjacent list, change its declaration to
QList<const Node*> _adjacent;
Otherwise you probably have to resort to const_cast, or remove the const qualifier from your function.
I am trying to create a custom sort for a vector of class pointers by using a sort predicate:
struct sort_by_airtime
{
inline bool operator() (const Network *n1, const Network *n2)
{
return (n1->airtime() < n2->airtime());
}
};
For each network, we sort by a float returned by airtime().
Now, I try to use this as follows:
std::vector<Network *> Simulator::sort_networks(std::vector<Network *> netlist, bool sort_airtime) {
std::vector<Network *> new_netlist = netlist;
if(sort_airtime) {
sort(new_netlist.begin(), new_netlist.end(), sort_by_airtime());
}
}
However, I get a lot of errors like this:
In file included from Simulator.cpp:7:
Simulator.h: In member function ‘bool Simulator::sort_by_airtime::operator()(const Network*, const Network*)’:
Simulator.h:48: error: passing ‘const Network’ as ‘this’ argument of ‘virtual float Network::airtime()’ discards qualifiers
Simulator.h:48: error: passing ‘const Network’ as ‘this’ argument of ‘virtual float Network::airtime()’ discards qualifiers
Am I not specifying the argument passed to the predicate properly? airtime() is implemented by classes that inherit the Network class.
The compiler is warning you that Network::airtime() is ignoring the const qualifiers on n1 and n2.
The solution would be to create a "const-correct" version of Network::airtime() (assuming it actually doesn't modify anything).
See this answer for an example.
Your member function should be declared as const member function as:
virtual float Network::airtime() const
^^^^^ //this makes the function const
because the pointers which you're using in operator() are pointing to const objects of type Network.
Network::airtime() is not const, and so can't be called via the const Network* you have in sort_by_airtime.
If possible, the best solution is to make airtime() const; otherwise change the sort_by_airtime arguments to Network*.
For my compsci class, I am implementing a Stack template class, but have run into an odd error:
Stack.h: In member function ‘const T Stack<T>::top() const [with T = int]’:
Stack.cpp:10: error: passing ‘const Stack<int>’ as ‘this’ argument of ‘void Stack<T>::checkElements() [with T = int]’ discards qualifiers
Stack<T>::top() looks like this:
const T top() const {
checkElements();
return (const T)(first_->data);
}
Stack<T>::checkElements() looks like this:
void checkElements() {
if (first_==NULL || size_==0)
throw range_error("There are no elements in the stack.");
}
The stack uses linked nodes for storage, so first_ is a pointer to the first node.
Why am I getting this error?
Your checkElements() function is not marked as const so you can't call it on const qualified objects.
top(), however is const qualified so in top(), this is a pointer to a const Stack (even if the Stack instance on which top() was called happens to be non-const), so you can't call checkElements() which always requires a non-const instance.
You cannot call a non-const method from a const method. That would 'discard' the const qualifier.
Basically it means that if it allowed you to call the method, then it could change the object, and that would break the promise of not modifying the object that the const at the end of the method signature offers.
You're calling a non-const method from a const method.
Because checkElements() isn't declared const.
void checkElements() const {
if (first_==NULL || size_==0)
throw range_error("There are no elements in the stack.");
}
Without that declaration, checkElements cannot be called on a const object.