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]
Related
#include <iostream>
class TEST
{
public:
int* a = new int;
TEST(int x)
: a(&x)
{
}
~TEST()
{
delete a;
}
};
int main()
{
{
int i = 2;
TEST T(i);
}
std::cin.get();
}
I tried to heap allocate integer in a TEST class and then delete it but
when I'm calling delete a in TEST class destructor I'm getting error in file called delete_scalar.cpp and I have no idea what does it mean and how to fix it. Where's the problem?
TEST(int x)
: a(&x)
{
}
This code is causing undefined behavior. It is making a point at a local int that goes out of scope immediately afterwards, leaving a as a dangling pointer to invalid memory. a is never pointing at dynamic memory (the new expression in the declaration of a is ignored when a is initialized in the constructor's member initialization list). That is why the delete fails later.
To do what you are attempting, you need to either:
move the new into the initialization list, eg:
int* a = nullptr;
TEST(int x)
: a(new int(x))
{
}
Or, if you want to keep using new in the declaration of a, then you can assign the value of that int from inside the constructor's body instead of in its initialization list, eg:
int* a = new int;
TEST(int x)
{
*a = x;
}
I got a situation where I have a class B having a protected array of A*. I have an another function A* func() which returns pointers to A objects stored in some other container. (for example std::map<int,A*> or A* arr[]).
For example the following implementation:
#include <iostream>
using namespace std;
class A {
public:
A(int _x): x(_x){};
int x;
};
class B{
public:
B() {
this->arr[0] = new A(1);
this->arr[1] = new A(2);
}
// use idx to index in to the internal array and return A*
A*& operator[](int idx); // return reference to pointer to avoid not a lvalue error
private:
// class B has this private array of A*
A* arr[2];
};
A*& B::operator[](int idx) {
return this->arr[idx]; // 0<=idx<=1
}
A* arr[2];
A* func(int x) {
return arr[x]; // 0<=idx<=1
}
int main() {
arr[0] = new A(12);
arr[1] = new A(14);
B b;
b[1] = func(1); // assign a new value
cout << b[1]->x << endl; // prints 14
}
// memory leaks of this program can be removed using `std::shared_ptr<A>` in the place of `A*`.
In this example, operator[]() returns a reference to a pointer, because returning pointer becomes rvalue and I will not be able to assign value to it (i.e. b[1] = func(1)).
My question is, is this reference to pointer returning recommended (other ways to achieve this )? or is this perfectly fine with raw pointers as well as with shared_ptr?
Thank You!
#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;
}
class A{
private:
int a;
public:
const int &ref = a;
};
int main() {
A obj;
obj.a = 20; // error cause private
obj.ref = 30; // not private but const so ERROR
return 0;
}
I'm trying to make a member variable accessible but read only through the interface. Currently I've tried this approach and it seems to compile fine. I made a const reference to my original variable int a and made it public. Is there anything that's wrong with this practice that I might be missing out? Or is this example safe and sound to use for practical purposes?
Nothing wrong with providing a member function with const correctness applied (and I've used that too and intend to do so always), but I'm asking is there any thing wrong with this way if I have to provide a variable that is only read-only.
Thankyou :)
class A{
private:
int a;
public:
const int &ref = a;
};
is there any thing wrong with this way if I have to provide a variable that is only read-only
There are at least a couple drawbacks with this design decision for class A.
1: Class Size
Also as Dieter Lücking mentions in a
comment:
increasing the size of the class, needlessly
2: Copy Semantics
It breaks the compiler generated copy assignment operator. For example, the following code behavior is generally desirable but doesn't work.
A obj1;
// ...
A obj2;
// make changes to 'obj2'
// Update 'obj1' with the changes from 'obj2'
obj1 = obj2; // This copy doesn't work!
More information:
Should I prefer pointers or references in member data?
Assignment operator with reference class member
Thinking in C++, 2nd ed. Volume 1 ©2000 by Bruce Eckel, 11: References & the Copy-Constructor
There are certain rules when using references:
A reference must be initialized when it is created. (Pointers can be initialized at any time.)
Once a reference is initialized to an object, it cannot be changed to refer to another object. (Pointers can be pointed to another object at any time.)
You cannot have NULL references. You must always be able to assume that a reference is connected to a legitimate piece of storage.
It may be possible to implement a custom assignment operator but that's more code to maintain (i.e., another drawback in my opinion).
#include <iostream>
class A
{
private:
int a;
public:
explicit A(int value) : a(value) {}
A& operator=(const A& other)
{
a = other.a;
return *this;
}
const int& ref = a;
};
int main()
{
A obj1(10);
std::cout << "1: " << obj1.ref << "\n";
A obj2(20);
std::cout << "2: " << obj2.ref << "\n";
obj1 = obj2;
std::cout << "1: " << obj1.ref << "\n";
return 0;
}
The idiomatic way to address this issue is to use a proper accessor function.
class A {
private:
int a;
public:
int getA() const { return a; }
};
The standard way to do this in C++ is by making the actual member private but including a public 'getter' method for the interface, as below:
class A{
private:
int a;
public:
int get_a() const { return a; }
A() : a(20) {}
};
int main() {
A obj;
int n = obj.get_a(); // n = 20
return 0;
}
The user cannot set the value of A::a but can use A::get_a to retrieve its value.
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* = ...