c++ passing a const object reference to a function - c++

error: passing 'const QByteArray' as 'this' argument of 'QByteArray& QByteArray::append(const QByteArray&)' discards qualifiers [-fpermissive]
since it is a convention to make objects const while passing as function arguments i have done it.
but now i am getting an error!!,
i dnt want to make the function constant as i have to convert data in qbyte array into short and then append it another array.
QByteArray ba((const char*)m_output.data(), sizeof(ushort));
playbackBuffer.append(ba);
I really need to pass this array into playbackbuffer;
It is giving me an error on playbackBuffer.append(ba);
please help
thanks in advance

This means you are calling a non-const member function on a const member. Presumably, your append function modifies the byte array. With a const reference, you shouldn't be modifying.

Basically what it says is that you're trying to append to a constant array.
If "append" does not change the object itself but just returns the two arrays appended, the method needs to be declared const to allow the call.

Consider this:
struct foo
{
void bar();
};
const foo f;
f.bar();
Here, in the call to bar(), the this pointer is &f. But bar() is not a const-function, so the type of this is foo*, which is incompatible with const foo*. (In other words, bar() says it might mutate the foo, but f says it's a non-mutablefoo.)
Either bar() needs to be marked as const (if it can), or f needs to not be const.
In your case, I'm going to assume you're using Qt and so cannot modify QByteArray (nor should you, since append is necessarily a non-const function), and instead suggest you get rid of the const on the object, which is preventing you from using the function.

So you are trying to call a non const function on a const object?
That's what passing a const xxx as 'this' argument would mean.
Since ultimately any member function really is
(Class * this, rest of arguments)

Either make your
QByteArray& QByteArray::append(const QByteArray&);
be
QByteArray& QByteArray::append(const QByteArray&) const;
(highly unlikely to solve anything) or just
QByteArray* pObj = const_cast<QByteArray*>(&your_obj)
if (pObj)
pObj->append(...

Related

Difference between Const usage in functions in c++

I'm having the below method with multiple const keywords. why are they used?
const int* MyClass::getvalue(const int input) const
if returning a pointer from a method, what are the ways to restrict the user from changing the pointer value and pointer itself?
First of all, having the return type for a value (as opposed to a reference or a pointer) being const is rather useless. The caller of the function can still copy the value to a non-constant variable anyway. For a reference or a pointer, it means that the referenced/pointed to object can not be modified. It can still be copied to a non-constant object though.
The argument being const means that the function can not change the argument. It is partly informational, partly helps the compiler choose optimizations, and for references or pointers means that whatever is referenced/pointed to can't be modified. For references there's also the semantic that you can pass temporary objects to the function.
The last const is for the function itself, and makes it so that the function can only be called on const objects. If you have a non-const MyClass object, this function can't be called on it. This const is part of the function signature, together with the function name and its argument types. That means you can have two overloaded functions with the same name and arguments, one being const qualified and one not.
I'm having the below method with multiple const keywords. why are they used?
const int MyClass::getvalue(const int input) const
^
This makes the return value const. There is no reason to use a return by const value. Some compilers will warn if you use const here. Note that conversely, a reference or a pointer to const object would be reasonable.
const int MyClass::getvalue(const int input) const
^
This makes the argument const. Whether a value argument is const or not makes little difference. A minor advantage of const is that you can know from the declaration that the local object won't change throughout the function, which can be helpful if the function is complex.
const int MyClass::getvalue(const int input) const
^
This makes a member function const. This allows the member function to be called on const instances of the class, but also prevents the function from modifying non-mutable members of the object.
if returning a pointer from a method, what are the ways to restrict the user from changing the pointer value and pointer itself?
There is no way of restricting the user from changing the value of a pointer object that you've returned to them, and there is never a need to do so.
You can restrict the user from modifying the pointed object by returning a pointer to const.
The last const specifies that getvalue() won't change the instance of MyClass it is called upon.
const int input declares a parameter of type int to the function getvalue() specified as const. Its value cannot be changed inside the function.
In the return type const is quite meaningless since the returned value can be assigned to a non-const-qualified int without problem.
what are the ways to restrict the user from changing the pointer value and pointer itself?
Read declarations backwards:
int const * const foo; // foo is a constant pointer to a constant int
int * const bar; // bar is a constant pointer to a int
int const * qux; // qux is a pointer to a constant int

Not understanding C++ type mismatch: const Foo* to Foo* const&

Having this set of objects and statements:
QSet<Foo*> set;
iterator QSet::insert(const T & value) //type of the function I want to call
const Foo * get() const //type of the function I use to get the argument
set.insert(get()); //the line showing up as error
I get the error "no known conversion for argument 1 from 'const Foo*' to 'Foo* const&". I guess I have trouble reading these types because I have no idea what I should do to make this work.
From what I've read, the const keyword applies to the type to its left with the exception of a top-level const which can be written to the left of the type it applies to. My guess would be that I have to convert get() to a reference but I'm unsure how to do that.
There seem to be a couple of misunderstandings here (both by the questioner and by some answers).
First, you said "My guess would be that I have to convert get() to a reference but I'm unsure how to do that". Let's try clearing this up:
1) "I have to convert get() to a reference" -- Actually, you don't!
iterator QSet::insert(const T & value) does indeed take a reference. But it's a reference to type T. So the question is, "what is type T"?
In this case, T=Foo *. So insert, in this instance of the template, is actually:
iterator QSet::insert(Foo * const & value) -- read it from right to left: insert takes a reference to a constant pointer to a Foo.
2) "I'm unsure how to do that [convert a pointer to a reference]" -- while you don't have to do it here, in general you do this by de-referencing the result of get. For example: *(get()).
Second, the compiler error. The error arises because there is a conflict:
a) get() returns a const Foo *
b) but set stores a Foo* -- NOT a const Foo *, so insert only accepts a changeable Foo
So you can't store a constant pointer inside your QSet<Foo*>. This makes sense because you can use set to access and change the Foos inside it, which you promise not to do with a const Foo.
This reference should be helpful:
https://isocpp.org/wiki/faq/const-correctness
You may also think whether you can just use a QSet<Foo> instead of a QSet<Foo*>. In the former case, things will probably behave how you expect.
You are trying to take a const Foo * and insert it into a QSet<Foo *>, but the compiler won't automatically convert a const Foo * to a plain Foo * in order to do so.
I solved the problem by changing the type of the set as follows.
QSet<Foo const*> set;
With this change, compilation succeeds.
You're violating the const-ness of the pointer returned from your get() function. get() returns a pointer to a const object of type Foo, but then you try to insert it into a vector of non-const Foo pointers. You need to const_cast the return value from get() or change the return type of get() from const Foo* to just Foo*.

Const Ref to const Pointer

I am working with a library that I can't change and have been set a task to complete with the library.
Although I have done the task and it works, I don't really understand why it works and whether I should do it.
I have a function in a cpp file
void Foo (const String &someName)
{
OtherFoo (&someName)
}
where Foo passes a reference to a const string and OtherFoo requires a pointer to const string to be passed to it.
So basically ref is a const string& and needs to be passed into OtherFoo as a const pointer (const & to const *)
Is what I've done OK? (passing the address of the ref to the function that requires a pointer to const string)
Is there any negatives with how I have passed the argument? Could someone explain exactly why it works?
Many thanks
Yes, this is a correct way of doing it. Indeed, taking the address of a reference yields in fact the address of the referent.
So in this case, the type of the expression &someName is actually const String *.
Be careful not to mix constness of the pointer and constness of the pointee though. In this case, when you say "const pointer", it's actually pointer to const which is not the same thing.

passing 'const' as ' this ' argument of [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
c++ passing a const object reference to a function
void SpectrumAnalyserThread::calculateFFT(AnalogData &frame, const QByteArray &playbackBuffer)
{
fft->window(frame.data(),frame.size());
fft->fix_fftr(frame.data(), qFloor(log(frame.size()) / log(2)), 0);
for(int i = 0; i < m_numSamples; ++i)
{
m_output.push_back(frame[i]);
}
fft->fix_fftr(m_output.data(), qFloor(log(m_output.size()) / log(2)), 0);
const QByteArray ba((const char*)m_output.data(), sizeof(ushort));
const_cast<QByteArray &>(playbackBuffer);
playbackBuffer.append(ba);
m_output.clear();
calculateMagnitude(frame);
}
I get the following error:
error: passing 'const QByteArray' as 'this' argument of 'QByteArray& QByteArray::append(const QByteArray&)' discards qualifiers [-fpermissive]
If I make the function const then it throws errors at
m_output.clear(), m_output.push_back(), which is obvious but I need to clear the buffer so that when the function is called again previous data does not get appended.
If you want to modify playbackBuffer then you should take the parameter as a non-const parameter:
QByteArray &playbackBuffer
This is completely independent of whether the member function of SpectrumAnalyserThread is declared const (which it shouldn't be if it modifies this' internal state).
Note that this line has no effect. To use the result of a cast you must do something with it. A statement that is a cast alone just performs the conversion and then throws the result of that conversion away.
const_cast<QByteArray &>(playbackBuffer);
You could do something like below but it risks undefined behaviour and is an abuse of the contract you have with callers of your function where you say, by taking a const reference, that you're not going to modify playbackBuffer.
const_cast<QByteArray &>(playbackBuffer).append(ba);
The problem is at
playbackBuffer.append(ba);
You want to mutate playbackBuffer, so don't pass it as a const reference.
const_cast returned an object of type QByteArray& (it wiped off const from the original type) but you didn't do anything with that object - the type of the playbackBuffer didn't change - it remained const QByteArray&.
You can do two things:
1) call class method on a temporary unnamed variable of type QByteArray& returned by the cast operator:
const_cast<QByteArray &>(playbackBuffer).append(ba);
2) assign return value of the cast operator to the local variable of type QByteArray& (if you want to use it again to call non-const member functions):
QByteArray& playbackBufferNonConstRef = const_cast<QByteArray&>(playbackBuffer);
playbackBufferNonConstRef.append(ba);
Regardless of this, you should first think of why passing an object as a const reference and then trying to trick it and change it after casting const away. If you declare function's argument as a const reference, your clients will believe that object passed to it won't be changed. But with this design they'll be getting unexpected results...

'Invalid conversion from some_type** to const some_type**'

I've got a function that requires const some_type** as an argument (some_type is a struct, and the function needs a pointer to an array of this type). I declared a local variable of type some_type*, and initialized it. Then I call the function as f(&some_array), and the compiler (gcc) says:
error: invalid conversion from ‘some_type**’ to ‘const some_type**’
What's the problem here? Why can't I convert a variable to const?
See: Why can't I pass a char ** to a function which expects a const char **? from the comp.lang.c FAQ.
You have a few options to get around what jamesdlin outlined in his answer.
You could use an intermediate variable.
some_type const* const_some_array = some_array;
f(&const_some_array);
You could change the parameters of f.
void f(some_type const* const* some_array);
You probably need to specify some more context, for instance is the argument passed data into or out of (or both?) the function?
Try making your variable const as well:
some_type const *some_array = ....;
This reads as "some_array is a pointer to a const some_type". The code can't modify the thing being pointed at. So you have to declare your variable const before passing it to the function.
(Edited...)