const compile error on class method - c++

I am receiving this error invalid conversion from ‘const char*’ to ‘char*’ from this code:
// in account.h
struct account {
char* get_name ( ) const;
char name[MAX_NAME_SIZE+1];
};
//in account.cxx
char* account::get_name ( ) const
{
return name;
}
Can someone please help me?

The return type should be const char* as well:
const char* get_name ( ) const;
It is because in a const member function, this pointer becomes a const, as a result of which every member of the class becomes const, which means name which is declared as char[N], becomes const char[N] in a const member function. const char[N] can converts into only const char*, hence you need to make the return type const char*.

You're returning a non const pointer. You want to return a const char:
// in account.h
const char* get_name ( ) const;
//in account.cxx
const char* account::get_name ( ) const
{
return name;
}
The reason is that your method is declared const, but the pointer you're returning could be used to modify name, which would be a violation of the method's const promise.

Since get_name is a const method, all the members of the implicit object are const in the context of that method. By returning name as a char *, you are dropping the const qualifier from name. You could return const char *.

Related

Calling Const function pointer

First off I would like to mention that this works with MSVC but not with clang. I am using Clang with c++11.
I have a function pointer:
typedef void (*Log) (const char* title, const char* msg, const char* file, int line);
I have this struct:
struct FunctionList
{
protected:
static const int kNbrMax = 32;
FunctionList();
bool Add(const void* f);
bool Remove(const void* f);
const void* m_functions[kNbrMax];
};
And this class:
template<typename T>
struct MessageFunctionList
: public FunctionList
{
public:
MessageFunctionList(T defaultFunction)
{
Add(defaultFunction);
}
void Call(const char* title,const char* cause,const char* file,int line)
{
for (unsigned long i = 0;i < m_nbrUsed;++i)
{
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
}
}
}
I am creating it like so:
static void DefaultLogMessageFunction(const char* title,const char* msg,const char* file,int line)
{
}
MessageFunctionList<Log> functionList(DefaultLogMessageFunction)
But I get the compile time error:
reinterpret_cast from 'const void ' to 'void ()(const char *, const
char *, const char *, int)' casts away qualifiers for line:
reinterpret_cast(m_functions[i])(title,cause,file,line);
So as far as I understand I am trying to cast my const list of functions to a non const value. That is not allowed which makes sense. So I tried the following:
const void* funcPtr = m_functions[i];
const T call = reinterpret_cast<const T>(funcPtr);
call(title, cause, file, line);
But that does not work either.
This works:
void* funcPtr = const_cast<void*>(m_functions[i]);
T call = reinterpret_cast<T>(funcPtr);
call(title,cause,file,line);
But I would like to avoid using a const cast. What am I doing wrong? How can I call this const function? Or is it simply not allowed because it does not know if the function being called is a const function or not? Or perhaps it is because my static function is not a member of a class so it can not be declared const?
You are storing the function pointers as const void*:
const void* m_functions[kNbrMax];
And you are trying to cast them to T and call it using reinterpret_cast:
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
However, reinterpret_cast cannot remove const qualifier from a type, therefore, you should first remove the const using const_cast:
reinterpret_cast<T>(const_cast<void*>(m_functions[i]))(title,cause,file,line);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
However, please note that const_cast engenders undefined behavior and is unsafe. So is calling a function pointer returned from reinterpret_cast if the original pointer was not actually a T.
Edit:
You can call a const qualified function pointer, however, then the reinterpret_cast should contain the const qualifier:
reinterpret_cast<const T>(m_functions[i])(title,cause,file,line);

C++ Pointer to const array of const pointers

I've created a const array of const pointers like so:
const char* const sessionList[] = {
dataTable0,
dataTable1,
dataTable2,
dataTable3
};
What is the correct syntax for a regular non-const pointer to this array? I thought it would be const char**, but the compiler thinks otherwise.
If you actually need a pointer to an array, as your title suggests, then this is the syntax:
const char* const (*ptr)[4] = &sessionList;
const char* const sessionList[] = { ... };
is better written as:
char const* const sessionList[] = { ... };
Type of sessionList[0] is char const* const.
Hence, type of &sessionList[0] is char const* const*.
You can use:
char const* const* ptr = &sessionList[0];
or
char const* const* ptr = sessionList;
That declares a pointer to the elements of sessionList. If you want to declare a pointer to the entire array, it needs to be:
char const* const (*ptr)[4] = &sessionList;
The same type as you declared for the array elements, with an extra * added:
const char* const *

Define a templated T as pointer

I want to define some generic pointer (? but not a void pointer) using this code:
class A
{
template<typename T>
using ptr = T*;
using ubyte = uint8_t;
public:
const ptr<ubyte>
getColor1() const {
return &colors[0];
}
const ubyte*
getColor2() const {
return &colors[0];
}
private:
ubyte colors[4];
};
However, the getColor1() won't compile.
What's the difference between this two functions ?
gcc says:
error: invalid conversion from 'const ubyte* {aka const unsigned char*}' to 'A::ptr<unsigned char> {aka unsigned char*}' [-fpermissive]|
Update:
The deleted answer says I could do this:
//option 1
template<typename T>
using const_ptr = const T*;
or
//option 2
const ptr<ubyte>
getColor() //remove cv-qualifier
{
return &colors[0];
}
From option1,
It constructs now to const const, what does const const means?
From option2,
Why just removing cv-qualifier makes this compile?
const ptr<ubyte> is the same as const (ubyte *) which is not the same as const ubyte (*). You are trying to return a const pointer to a non-const char, which the compiler won't allow because you've declared the function itself const; all members become const because of that. The compiler won't automatically cast const to non-const without a const_cast.
To make the difference clearer, the first is a const pointer to a non-const char and the second is a non-const pointer to a const char. The first allows the pointed-to characters to change, even though the pointer itself can't change. Since the function was marked as const it can't return anything that would allow its members to be modified.
The best way to fix it:
ptr<const ubyte>
getColor1() const {
return &colors[0];
}
Because of the syntax of your ptr template, const ptr<ubyte> first makes it a ubyte*, then applies the const, resulting in a ubyte * const, a constant pointer to an ubyte.
In order to return a pointer to a const ubyte, you need to feed a const ubyte into your pointer template, so constness is applied first:
ptr<const ubyte>
1) "what does const const means?"
const T* const pT = new T;
Means const pointer pT - you cannot assign pT to another object;
to a const object of type T - you cannot change the object which is pointed by pT.
2) "Why just removing cv-qualifier makes this compile?"
getColor1()
method without const modifier can modify the object. It now returns A::ubyte* which can be converted to a const type such as declared as return type: A::ubyte* const (const ptr< ubyte > )

What does invalid initialization of reference mean?

My code is like this
std::string & Product::getDescription() const {
return &description;
}
I've tried it all different ways with description and *description and nothing works, but when I take off the reference part of the return type it works fine. The thing is though that we're supposed to use &. I'm really confused as to why nothing works. Also earlier in the project there was the code:
void Product::setDescription(const std::string &newUnits) const {
units = newUnits;
}
With units being declared as a global public variable. The exact error it gives me is:
error: invalid initialization of reference of type ‘std::string& {aka std::basic_string&}’ from expression of type ‘const string {aka const std::basic_string}’
when you initialize reference you don't use & operator on variable:
int i = 0;
int& j = i; // now j is reference for i
similarly in the function, return variable without &:
std::string& Product::getDescription() const {
return description;
} // equivalent for std::string& returned = description;
In addition you are allowed to return only const reference from const function. So this should be:
const std::string& Product::getDescription() const {
return description;
}
or
std::string& Product::getDescription() {
return description;
}
When returning a reference you don't use the address-of operator:
class Product
{
std::string description;
const std::string& get_description() const { return description; }
void set_description(const std::string& desc) { description = desc; }
};
That's a const member function, meaning that the object that it's called on (and its members) are const within the function. You can't return a non-const reference to a member.
You can return a const reference from a const function:
const std::string & Product::getDescription() const;
and a non-const reference from a non-const function
std::string & Product::getDescription();
Assuming description has type std::string, you would return the reference with just return description;, with no &.
The set function can't be const, since it modifies the object.
Your method Product::getDescription() const should return a reference to a const object, because the method is const. What is more, &description is pointer to the string, because in that context & is the address-of operator. You do not initialize a reference from a pointer. Use the following:
const std::string & Product::getDescription() const { return description; }

C++: Calling a non-const function in an object pointed from a const pointer (error C2662)

I have a struct with a const pointer to an object. It is const so that the pointer won't change, I do not wish to have the object constant. I'd like to call a non-constant function in that object, thus receiving the following error:
error C2662:
'my_namespace::MyClass::myFunc' :
cannot convert 'this' pointer from
'const my_namespace::MyClass' to
'my_namespace::MyClass &'
Conversion loses qualifiers
struct MyStruct
{
MyStruct( const MyClass* init_my_class_ptr );
const MyClass* my_class_ptr;
};
...
struct_instance.my_class_ptr->aNonConstFunc();
...
Assume I can't make aNonConstFunc() const.
Change your struct to:
struct MyStruct
{
MyStruct( const MyClass* init_my_class_ptr );
MyClass* const my_class_ptr;
};
That will make the pointer, instead of the pointee, const.
More elaborate explanation (also see Wikipedia): the const keyword is applied to whatever comes before it, except in case there's nothing in front, then it applies to what comes after it. So:
const A * object; // Non-const pointer to const A
A const * object; // Non-const pointer to const A
A * const object; // Const pointer to non-const A
const A * const object; // Const pointer to const A
A const * const object; // Const pointer to const A
Now, this is just personal preference, but this is why I always put const after whatever is supposed to be const. When applied everywhere in your code, this makes it very easy to figure out what exactly is supposed to be const. No need to go decipher if the const applies to statement before or after it.
Change const MyClass* my_class_ptr; to MyClass* const my_class_ptr;
const MyClass* my_class_ptr; declares my_class_ptr to be a pointer to a const MyClass object.
MyClass* const my_class_ptr declares my_class_ptr to be a constant pointer to a MyClass
object and that's what you need.
The use of const.
The general rule is that const is applied to the object on the left of const. Unless const is the left most part of the declaration then it is applied to the right.
// Thus these two are equivalent.
const char* data1; // 'pointer to' const char (const applied to right because it has nothing on left)
char const* data2; // 'pointer to' const char
I prefer putting const on right as I can then consistently use the rule of reading types from right to left.
char const* data3; // 'pointer to' const char (reading right to left)
char* const data4; // const 'pointer to' char (reading right to left)
This is a style pref and lots of people prefer the const on the far left (and are smart enough to auto read the declaration in their head :-).
BUT Where it becomes important is when you add typedefs into the mix:
typedef is NOT a textual substitution, if defines a type alias (or synonym).
typedef char* CHARP;
const char* data5a; // 'pointer to' const char
const CHARP data5b; // const ''pointer to' char' ***(NOT THE SAME AS above)***
char* const data6a; // const 'pointer to' char
CHARP const data6b; // const ''pointer to' char'
So when you start using typedefs the meaning can change (if you put const on the far left) and just do a textual cut and paste when creating your typedefs. But th
Finally to answer the question.
You want a const pointer in your structure. To do this make sure the const is on the right side of the '*' symbol.
struct MyStruct
{
MyStruct(MyClass* const init_my_class_ptr)
: my_class_ptr(init_my_class_ptr)
{}
MyClass* const my_class_ptr; // const pointer to MyClass
};