#include <iostream>
using namespace std;
class A
{
public:
A(int x){ a = x;}
~A();
private:
int a;
};
int main()
{
A* a = new A(10);
void** p;
p = &a;
return 0;
}
After compiling with g++ (GCC) 4.1.2 20080704 , I am getting following error :
test.cpp: In function 'int main()':
test.cpp:17: error: invalid conversion from 'A**' to 'void**'
There's one star to much. void* can already hold any pointer, without casts:
int main()
{
A* a = new A(10);
void* p;
p = &a;
return 0;
}
This works for multiple levels, even:
int main()
{
A* a = new A(10);
A** aa = &a;
A*** aaa = &aa;
void* p = &aaa;
}
This works because A*** is a pointer to a A**.
You need to use reinterpret_cast:
It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type.
In this case your expression will be &a which has the type A** and your new_type will have the type void**:
p = reinterpret_cast<void**>(&a);
Do have a care here as C++ isn't really that fond of the void type and your code is very likely going to violate Type Aliasing Rules.
In my mind a cast to void** is an indication that a template should probably be used. Without seeing your code I can't guarantee that, but, if you want to fill me in anymore in the comments perhaps I can help.
You can't just assign the value of one type (A**) to the variable of another one (void**), if it can't be converted implicitly. You need to explicitly convert value from one type to another:
class A
{
public:
A(int x){ a = x;}
~A();
private:
int a;
};
int main()
{
A* a = new A(10);
void** p;
// use `reinterpret_cast'
p = reinterpret_cast<void**>(&a);
// C-style cast works but it is a bad practice in C++
p = (void**)&a;
return 0;
}
Related
I'm happy to post my first question here .
so i was play a little bit with pointers to understand the concept and i found this error
error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
here is the code :
#include <iostream>
using namespace std;
int main(){
int* pa,pb,pc,a,b,c;
pa = &a;
cin >> a;
cout <<"the value of a :"<<a<<endl;
cout <<"the value of pointer of a :"<<*pa<<endl;
// the problem begins when reading values of b :
pb = &b; //<== error
cin >> b;
cout << "the value of b : "<<b<<endl;
cout <<"the value of pointer of b" <<*pb<<endl;
return 0;
}
i don't know why it went successfully with variable a but failed with the same syntax in b ?
EDIT : thanks for everyone , i know this question is very simple but i've learned from you :)
The * binds to the variable name, not the type. So what you really want is:
int *pa,*pb,*pc,a,b,c;
In the declaration
int* pa,pb,pc,a,b,c;
Only pa is declared as int*. The other variables are declared as int.
You would need to declare the variables as
int *pa, *pb, *pc, a, b, c;
A common recomendation is to declare one variable per line (see for example ES.10: Declare one name (only) per declaration), because * belongs to the variables, not the type and this can be confusing. Your
int* pa,pb,pc,a,b,c;
is actually
int* pa;
int pb;
int pc;
int a;
int b;
int c;
But you wanted:
int* pa;
int* pb;
int* pc;
int a;
int b;
int c;
In other words, you get the error becaue in your code pb is an int but &b is an int*. The first assignment is ok, because pa is a pointer.
Another common recommendation is to always initialize your variables (see ES.20: Always initialize an object), so even nicer would be
int a = 0;
int b = 0;
int c = 0;
int* pa = &a;
int* pb = &b;
int* pc = &c;
And once you got it straight what type pa, pb and pc are you can use auto to get "just the right type":
auto a = 0; // 0 is an integer literal of type int
auto b = 0;
auto c = 0;
auto* pa = &a; // auto would be fine too, &a is a int*
auto* pb = &b;
auto* pc = &c;
Regarding the following C++ program:
class Base { };
class Child : public Base { };
int main()
{
// Normal: using child as base is allowed
Child *c = new Child();
Base *b = c;
// Double pointers: apparently can't use Child** as Base**
Child **cc = &c;
Base **bb = cc;
return 0;
}
GCC produces the following error on the last assignment statement:
error: invalid conversion from ‘Child**’ to ‘Base**’
My question is in two parts:
Why is there no implicit conversion from Child** to Base**?
I can make this example work with a C-style cast or a reinterpret_cast. Using these casts means throwing away all type safety. Is there anything I can add to the class definitions to make these pointers cast implicitly, or at least phrase the conversion in a way that allows me to use static_cast instead?
If this was allowed, you could write this:
*bb = new Base;
And c would end up pointing to an instance of Base. Bad.
Pointers are virtual address. Normally you are responsible for what you do with it. Using msvc 2019. I can cast one to base, but not two:
example 1:
int p;
int *p1 = &p;
int **p2 = &p1; //OK
example 2:
struct xx {};
struct yy : public xx {};
yy p;
yy *p1 = &p;
xx **p2 = &p1; //Just a strange error
example 3:
struct xx {};
struct yy : public xx {};
yy p;
xx *p1 = &p;
xx **p2 = &p1; //OK
I'm having some trouble with the class casting in C++.
To learn, I wanted to create a class which just make operations, like sums, but it seems to crash everytime I launch it.
Here is my simple classes:
#include <iostream>
class CCalculation {
public:
CCalculation() {};
virtual int calculate() = 0;
};
class CCalc_CONST : public CCalculation {
int x;
public:
CCalc_CONST(int a) : x(a) {};
int calculate() { return x; };
};
class CCalc_ADD : public CCalculation {
CCalculation *x;
CCalculation *y;
public:
CCalc_ADD(CCalculation *a, CCalculation *b) {
this->x = a;
this->y = b;
};
int calculate() {
std::cout << "Calculation...\n";
return x->calculate() + y->calculate();
};
};
And my test:
CCalculation *a = &CCalc_CONST(4);
CCalculation *b = &CCalc_CONST(1);
CCalculation *c = &CCalc_ADD(a,b);
std::cout << "res: " << c->calculate() << "\n";
It seems to crash everytime (I got no compiler error or warning).
The only way to run it I found is when I'm printing a->calculate and b->calculate at the CCalc_ADD construction. I have absolutely no clue why i need to call the calculate function to make it work.
Can someone please explains to me how to actually do it ?
First of all, you should turn on all warnings (see docs to your compiler, in gcc -Wall)
Then you will see, that your compiler will blame you:
1.cpp: In function 'int main()':
1.cpp:56:37: error: taking address of temporary [-fpermissive]
1.cpp:57:37: error: taking address of temporary [-fpermissive]
1.cpp:58:37: error: taking address of temporary [-fpermissive]
Actually, here
CCalculation *a = &CCalc_CONST(4);
you just create temporary object that will be destroyed imminently after creation and you get broken pointer.
You have 2 alternatives:
create objects in dynamic memory (but in this case I will recommend make complex calculation owner of simpler)
class CCalc_ADD : public CCalculation {
std::unique_ptr<CCalculation> x;
std::unique_ptr<CCalculation> y;
public:
CCalc_ADD(CCalculation *a, CCalculation *b):x(a), y(b)
{
};
int calculate() {
std::cout << "Calculation...\n";
return x->calculate() + y->calculate();
};
};
std::unique_ptr<CCalculation> a(new CCalc_CONST(4));
//...
CCalc_ADD c (std::move(a), std::move(b));
replace pointers with references. Then you can use value semantics.
To get a working program you don't even need to use new:
CCalc_CONST a(4);
CCalc_CONST b(1);
CCalc_ADD c(&a,&b);
std::cout << "res: " << c.calculate() << "\n";
You're not using new. Test like this:
CCalculation *a = new CCalc_CONST(4);
CCalculation *b = new CCalc_CONST(1);
CCalculation *c = new CCalc_ADD(a,b);
You can weed out things like address-of on temporaries by compiling with -Wall, which enables all compiler warnings. The compiler is your friend and is there to help. Love the compiler.
You are trying to access temporary objects that are no longer alive. Use operator new for allocating memory for an object and calling its constructor.
CCalculation *a = new CCalc_CONST(4);
CCalculation *b = new CCalc_CONST(1);
CCalculation *c = new CCalc_ADD(a,b);
I have tried it with GCC and it issues a very clear warning about this:
test.cpp: In function ‘int main()’:
test.cpp:35:33: error: taking address of temporary [-fpermissive]
test.cpp:36:37: error: taking address of temporary [-fpermissive]
test.cpp:37:37: error: taking address of temporary [-fpermissive]
the below code doesn't compile
void aaa(const int **a) {
}
int *a[] = {new int[2]};
aaa(a);
I got "cannot convert parameter 1 from 'int [1]' to 'const int *" in VS2010 and similar error in gcc
when I change my declaration to:
int const *a[] = {new int[2]};
or
const int *a[] = {new int[2]};
it compiles, but I don't understand why it doesn't accept a non const variable declaration
The type of a is int*[]; the type you want is int const**.
int*[] converts to int**, but this will not convert implicitly to
int const**. Consider the following code to understand why:
static int const ci = 42;
void aaa( int const** out )
{
*out = &ci;
}
int
main()
{
int* pa;
aaa( &pa ); // NOT LEGAL, because...
*pa = 0; // would now change ci
std::cout << ci << std::endl;
return 0;
}
As you can see, allowing this conversion would break const without
requiring a cast.
Depending on what you are doing, you might want to use:
void aaa( int const* const* out );
The implicit conversion of int** to int const *const * is legal.
(Otherwise, you'll need a const_cast somewhere, to tell the compiler
that you know what you're doing, and that it isn't really a problem.)
The function aaa expects a pointer-to-pointer-to-constant-int.
Your variable a is a pointer-to-pointer-to-int.
It is an error to assign the latter to the former.
both int const *a[] and const int *a[] is actually the same thing, matching the signature of aaa. If you tried int * const a[], that would be a different type (pointer-to-constant-pointer-to-int) and you would trigger the type error again.
If you want your function aaa to take a constant-pointer-to-pointer-to-int, you need to write aaa(int ** const a), but having a const-ness on parameter values has actually no effect on what you can call with.
Edit: "But isn't constness added implicitly - done with an implicit cast? (Which is the actual question)"
Constness can be implicitly added to the value you are passing, e.g.
void aaa(const int a) {}
int b=5;
aaa(b);
... or one level pointer
void aaa(const int* a) {}
int *b=new int;
aaa(b);
... but cannot be added deeper. For example this is invalid:
void aaa(const int** a) {}
int* b=new int;
int** c=&b;
aaa(c);
I think James Kanze explains it much better in his answer.
class A {
public: int i;
};
A *a = new A();
How to get the address of a->i? I tried &a->i and also &(a->i) but those generate compile time errors:
"left of '.i' must have class/struct/union type"
You have not provided the same code you tried to compile. Always copy and paste. The tells in your code are that you don't have a syntactically correct class declaration or variable declaration, and that your error message talks about ".i" when you've claimed you've only used a->i. Here's working code:
#include <stdio.h>
class A {
public:
int i;
};
int main() {
A* a = new A();
int* i = &a->i;
printf("a: %p\na->i: %p\n", a, i);
return 0;
}
Ultimately, the syntax you say you tried for getting the address of the member was correct. The syntax the error message says you tried was a.i. That doesn't work, and for the reason the error message gave. The variable a is not a class, struct, or union type. Rather, it's a pointer to one of those types. You need to dereference the pointer to get at the member.
When I run it, I get this:
$ ./a.out
a: 40748
a->i: 40748
The addresses are the same because A is a simple class, so this output is to be expected. The first member is frequently placed at the very start of a class's memory. Add a second member variable to the class and get its address; you should see different values then.
In c++:
class A {
public: // note colon after public
int i;
}; // note semicolon after bracket
A *a = new A(); // note *a not a*
to print:
cout << ios::hex << &a->i << endl;
For me this seems to work ok.
&a->i should work. In your case since the class just has one public integer both the address of a and i will be the same.
You're on the right track, but from the compile error you mention, it sounds like you were typing "&a.i"
class A
{
public:
int i;
};
...
A *a = new A();
int *i = &a->i;
This code appears to compile?
class A {
public:
int i;
};
int main() {
A *a = new A();
int *x = &a->i;
return 0;
}
The following works for me using g++
class A
{
public:
int m_i;
};
int
main()
{
A* a = new A();
int* i_ptr = &(a->m_i);
return 0;
}
I am guessing you mean A* a = ... and not A a* = ...