The following code fails to compile with two errors on the line 'func(&pobj);' stating "Cannot convert 'X * *' to 'const X * *' in function main()" and "Type mismatch in parameter 1 (wanted 'const X * *', got 'X * *') in function main()" even though its the correct way to pass pointer parameters. And also on commenting this particular line i.e 'func(&pobj);' and uncommenting the two lines above it which declares a new 'const' pointer 'pp' of required type (in parameter of func) but still throws an error on the line which declares and assigns 'pp' saying "Cannot convert 'X * *' to 'const X * *' in function main()".
using X = int;
void func(const X **);
int main() {
X *pobj = new X(58);
// const X **pp = &pobj; // ERROR
// func(pp);
func(&pobj); // ERROR
}
I believe that this is the correct way to pass constant pointers as parameters and I just don't understand why the program fails to compile. Can anyone point out the fault in the code above and suggest me the correct logic/syntax if I am wrong? Thanks in advance.
UPDATE:
This question was marked as duplicate but it doesn't have the answer that solves the problem at hand. Thus I would love it if the Stack Overflow community would help me to solve my problem here. Thanks.
Do this:
const X * pobj = new X(58);
// ^^^^^^
func(&pobj);
Now pobj is a pointer-to-const-X, and its address is of type const X ** as required.
If you want to retain the original (mutable) pointer, you need to make a new const pointer first:
X * p = new X(58);
const X * q = p;
func(&q);
You will need to apply const to pointer-to-pointer:
void func(X *const *);
...
X * const *pp=&pobj; // ERROR
func(&pobj); // ERROR
...
void func(X * const * obj) { // module code goes here
}
If the answer of Ajay is not appropriate, because You cannot change the interface of func(),
and if the answer of Kerrek does not work, because func() changes the pointer, which must be assigned back, that does not happen:
X * p = new X(58);
const X * q = p;
func(&q);
p = q; // errror
then simply use a cast:
func(const_cast<const X**>(&p))
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Kindly tell me what's wrong with the code. It is showing many errors. The error statements and problem statement is given below:
First error is in the overloaded dereference operator. It says pmemory was not declared in this scope.
2nd error is in the main function where I use
ptrFloat ptr1 = &var1;
it shows error "conversion from 'Float' to non-scalar type 'ptrFloat' requested".
And in the next line of above mention statement save error..
in next line it show that (no match for operator <<) .
and in the very next line it show the same error as above.(no match for operator).
And at last it show again the same error that (no match for operator)
The question statement is given below:
Remember fmem_top is an index to fmemory which points to the next available place where a float value can be stored. And pmem_top is the similer index to pmemory.
Create a class called Float . We’ll use it to model numbers of type float that are stored in fmemory instead of real memory. The only instance data in Float is its own “address”; that is, the index where its float value is stored in fmemory. Call this instance variable addr. Class Float also needs two member functions. The first is a one-argument constructor to initialize the Float with a float value. This constructor stores the float value in the element of fmemory pointed to by fmem_top , and stores the value of fmem_top in addr . This is similar to how the compiler and linker arrange to store an ordinary variable in real memory. The second member function is the overloaded & operator. It simply returns the pointer (really the index, type int ) value in addr .
Create a second class called ptrFloat . The instance data in this class holds the address(index) in pmemory where some other address (index) is stored. A member function initializes this “pointer” with an int index value. The second member function is the overloaded * (dereference, or “contents of”) operator. Its operation is a tad more complicated.
It obtains the address from pmemory , where its data, which is also an address, is stored. It then uses this new address as an index into fmemory to obtain the float value pointed to by its address data.
float& ptrFloat::operator*()
{
return fmemory[pmemory[addr]];
}
#include<iostream>
#include<conio.h>
using namespace std;
class Float
{
protected:
float *fmem_top;
float **addr;
float fmemory[10];
public:
Float(float a)
{
fmem_top=fmemory;
addr=&fmem_top;
*fmem_top=a;
fmem_top++;
}
Float operator & ()
{
return *fmem_top;
}
};
class ptrFloat: public Float
{
private:
int *pmem_top;
int pmemory[10];
public:
ptrFloat(int abc) : Float(abc)
{
pmem_top=pmemory;
*pmem_top=abc;
pmem_top++;
}
ptrFloat operator * ()
{
return fmemory[pememory[addr]];
}
};
int main ()
{
Float var1 = 1.234;
Float var2 = 5.678;
ptrFloat ptr1 = &var1;
ptrFloat ptr2 = &var2;
cout<<"*ptr1 = "<< *ptr1;
cout<<"*ptr2 = "<< *ptr2;
*ptr1 = 7.123;
*ptr2 = 8.456;
cout<<"*ptr1 = "<< *ptr1;
cout<<"*ptr2 = "<< *ptr2;
getch();
return 0;
}
I'm not sure what's going on here, but this is what Clang has to say:
prog.cc:33:48: error: array subscript is not an integer
ptrFloat operator*() { return fmemory[pmemory[addr]]; }
^~~~~
There's a typo in the line here - you'd written pememory. But addr is a float**.
prog.cc:40:12: error: no viable conversion from 'Float' to 'ptrFloat'
ptrFloat ptr1 = &var1;
^ ~~~~~
ptrFloat is a class derived from Float, not a Float*.
What's your intent with this code?
As an aside, the clang compiler has great and helpful error messages. If you don't/can't install clang on your computer - I think it's a pfaff to set it up on Windows, I don't know - you can quickly test your code on an online compiler such as Wandbox and see if clang's output gives better clues. Here's your code running there - I had to strip out conio.h and getch as they're Windows-only: http://melpon.org/wandbox/permlink/4iCa61Rqysqc7Lpl
The first error is a typo you wrote pememory.
The second error appears because you didn't code any transformation between Float and ptrFloat.
You should add a copy constructor to Float:
Float(const Float& a) : Float(*a.fmem_top) {}
And then a conversion constructor to ptrFloat:
ptrFloat(Float a) : Float(a) {
pmem_top=pmemory;
*pmem_top=abc;
pmem_top++;
}
PS: your code has a lot of problems. I don't really get what you are trying to do, but, for instance, you can't have float typed variables as array subscripts.
I have a very simple method with the following prototype:
void *station_0(void* p1);
I am calling it like this:
product_record r;
pthread_create(thread, NULL, station_0, (void *)&r);
Inside this method all I need to do is cast p1 to an already defined struct product_record, I am currently trying this inside of my method:
product_record p = (product_record)p1
but the compiler complains on that line(above) saying error: invalid conversion from 'void*' to 'int' [-fpermissive]
I don't think I understand this warning at all. Why cannot I simply cast a void* to my struct?
You need two steps - convert the void pointer to a product_record pointer and then de-reference that. This can be done in the line
product_record p = *(static_cast<product_record *>(p1));
How can I get the memory address of a constant variable in c++. When I try to get this I get an error.
int const nValue = 5;
int * pnPtr = &nValue;
The error message is given below. I'm using visual studio 2010.
Error 1 error C2440: 'initializing' : cannot convert from 'const int *' to 'int *'
Is there any method to do this?
"Is there any method to do this?"
Sure. You need a const int* pointer to get this address, as the error message says:
int const nValue = 5;
const int * pnPtr = &nValue;
// ^^^^^
An int* pointer would allow to modify the nValue, which is not legal, and that's why the compiler complains.
As for your comment. A const int* can be used to point to a regular int and a const int. The point is just you can't use it to modify the underlying memory at the address it holds.
The pointer variable itself isn't const and can be changed to a different address.
If you want both attributes you'll need to write:
const int const * pnPtr = &nValue;
// ^ ^
// | + prevents changing the pointer after initialization
// +- prevents changing the underlying memory
You need to use a pointer to a const int value like this:
int const *ptr = &nValue;
C++ is strict regarding const-correctness, and this is a good thing.
If I do the following all is ok:
char* cp = "abc";
void* vp = NULL;
vp = static_cast<void*>(cp);//ok
cp = static_cast<char*>(vp);//ok
But the following is not:
char** cpp = &cp;
void** vpp = NULL;
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast':
//cannot convert from 'char **' to 'void **'
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast':
//cannot convert from 'void **' to 'char **'
Please can someone explain to me why the second examples are not allowed. Please don't quote the C++ standard as your whole answer, because I've already seen answers that quote it, and I don't understand what they meant. I want to understand why the second examples don't work (ie. if you could give an example where it would be dangerous that would be a great help). Because I don't get it. To me, both examples are casting pointers. Why does an additional level of indirection make any difference?
A void * pointer can point at "anything", and it is valid to convert all pointers to a void *, and it is valid to convert all pointers from void * to some other type.
However, a void ** is a pointer that points to a void * value. And a char ** is a pointer that points to char * value. These types don't point to the types that are convertible from one another. You can, if you NEED to do this, use void **vpp = reinterpret_cast<void **>(cpp);, but it's "not safe" (you are basically telling the compiler "Look, I know what I'm doing here, so just do it", which may not do what you actually expected...)
The restriction is to avoid breaking the type system. The first conversion is fine:
type *p = ...;
void *vp = p;
While you are giving away the type, you cannot inflict too much damage to the original value without since there is little to be done with a void object and all changes to vp are local to the pointer and cannot affect p.
If the second case was allowed:
type **p = ...;
void **vp = p;
Then perfectly looking and correct code could break your application. For example:
int *parray[10];
int **p = parray;
void **vp = p;
*vp = new double(); // now parray[0] is a pointer to a double object,
// not a pointer to an int!!!
The type system has been subverted.
That is, the problem is that in the second case there are operations that can be applied to the destination pointer that can modify the original object and cause bugs. Similar examples can be found with const other cases (you can convert int* to const int*, but you cannot convert int** to const int**...).
The const modifier in C++ before star means that using this pointer the value pointed at cannot be changed, while the pointer itself can be made to point something else. In the below
void justloadme(const int **ptr)
{
*ptr = new int[5];
}
int main()
{
int *ptr = NULL;
justloadme(&ptr);
}
justloadme function should not be allowed to edit the integer values (if any) pointed by the passed param, while it can edit the int* value (since the const is not after the first star), but still why do I get a compiler error in both GCC and VC++?
GCC: error: invalid conversion from int** to const int**
VC++: error C2664: 'justloadme' : cannot convert parameter 1 from 'int **' to 'const int **'. Conversion loses qualifiers
Why does it say that the conversion loses qualifiers? Isn't it gaining the const qualifier? Moreover, isn't it similar to strlen(const char*) where we pass a non-const char*
As most times, the compiler is right and intuition wrong. The problem is that if that particular assignment was allowed you could break const-correctness in your program:
const int constant = 10;
int *modifier = 0;
const int ** const_breaker = &modifier; // [*] this is equivalent to your code
*const_breaker = & constant; // no problem, const_breaker points to
// pointer to a constant integer, but...
// we are actually doing: modifer = &constant!!!
*modifier = 5; // ouch!! we are modifying a constant!!!
The line marked with [*] is the culprit for that violation, and is disallowed for that particular reason. The language allows adding const to the last level but not the first:
int * const * correct = &modifier; // ok, this does not break correctness of the code