C++ pointer to a class member in the same class [Conceptual]? - c++

`
class A{
public:
int x;
A* p;
};
int main(){
A obj1 = new A(); //no suitable constructor exists to convert from "A *" to "A"
A *obj2 = new A(); //Works fine
return 0;
}
`
Why is an object of class A declared as a pointer to that class, by default?
In other words, why does obj1 doesn't work but *obj2 does.

The new operator returns a pointer, so you can assign it only to a variable of pointer type.
You can use A obj1 = A();, which will simply call the constructor (without allocating dynamic memory, which is what new does) and return a A, not a A*.

No. Why is an object of class A declared as a pointer to that class, by default? Is incorrect. An object of class is just an object of that type and no pointer there.
The keyword new is used to allocate dynamic memory for a pointer. That is a memory must be cleaned up manually when you're done with it otherwise you will face a memory leak.
A* pObj = new A; // ok
A obj = new A; // error
A obj = *pObj; // ok:
Above obj is just an instance of class A and pObj is a pointer to an object of class A so inside the pointer there's the address of the object so to access it we dereference the pointer:
obj = *pObj = 0; // De-referencing pObj and assigning the value it points to to obj.
Finally clean up:
delete pObj; // ok
delete obj; // error

Related

how delete class variable in struct?

InitMyObject(MyObject* ptr)
{
*ptr = MyObject();
}
struct Data
{
MyObject obj;
};
extern Data data;
// ...
InitMyObject(&data.obj);
delete &data.obj; // ? is this ok
How I can delete (call deconstructor) data.obj, I also try Data::obj as pointer (nullptr default) then pass the pointer but crashed on Init.
How I can delete (call deconstructor) data.obj
The destructor of data will destroy its subobjects. Since data has static storage, it is automatically destroyed at the end of the program.
delete &data.obj; // ? is this ok
No. You may only delete the result of a non-placement new expression. You may not delete a pointer to a member object.

What will be happen if you dynamically allocates memory for one object of the class as an argument?

class Example
{
private:
Example* pointer;
Example* pointer2;
public:
Example();
void setPointer2(Example* object);
};
Example::Example()
{
pointer = new Example();
}
void Example::setPointer2(Example* object)
{
this->pointer2 = object;
}
int main()
{
Example object;
object.setPointer2(new Example());
return 0;
}
Delete is not important. I just want to know what is the differences between this two object which is adresses holding by pointer and pointer2. Are they differently allocated? The actual question is, does it matter where to use the "new" operator?
A major problem you have in your code is infinite recursion! The constructor you have defined:
Example::Example()
{
pointer = new Example();
}
creates a new object of its own type. This will call the constructor (again), and that call will call the constructor (again and again...)
But, other than that issue, it doesn't really matter whether you create a new object by directly assigning its address to pointer or if you create the object elsewhere and then assign its address (later) to pointer2. Both will point to an object of the class.

error: 'new' cannot appear in a constant-expression

class A
{
int data;
public:
void display()
{
cout<<"Value is "<<data;
}
void set_data(int x)
{
this->data = x;
}
A object = new A();
};
When I run the above code, I get the error stating "new cannot appear in constant expression". Why is it so?
Operator new returns a pointer but A is not a pointer type. You want A*:
A* object = new A();
You also want to move the above statement outside your class body and place it into appropriate function such as main():
int main() {
A* p = new A();
// do work
delete p;
}
That being said you either don't need a pointer at all and you can simply use an object with automatic storage duration:
A object;
Or you want to consider using a smart pointer such as std::unique_ptr:
std::unique_ptr<A> p = std::make_unique<A>();
class A
{
public:
A * object = new A(); // In any case not: "A object = new A();"
};
Or:
class A
{
public:
A object;
};
-
See (let's assume, for a moment, that you don't get the error), in both cases, on the first construction of A object, it creates another A object as a data-member. This A data-member (let's call it object.object ) creates in its turn another A as its data-member (let's call it object.object.object), and so to infinity (or until no more memory). I mean, as a data-member, it can't be either as A* object = new A();, or as A object;
-
I am not sure what was your intention, but if you want to link one A-object to another A-object, the class should be something like that:
class A
{
public:
A * object = nullptr
};
you have to make object of class A into main().
void main(){
A object;
}
First of all, you cannot create an object in the class declaration. Class declaration is like a blue print of the class. It is to say these are the components of my class - variables and member functions. You cannot instantiate anything inside it as no memory is allocated during this stage.
Note that you can instantiate an object inside one of the member function including constructor. These are called during object creation when memory is allocated.
Even if you use this statement inside a constructor you will go into an infinite loop as the constructor calls its constructor and so on until you have memory overflow.
You can declare the object in main like this:
int main() {
A obj = new A();
//other operations
} //Object A is destroyed once you come out of main.
Or dynamically like this
int main() {
A* obj = new A(); //dynamic allocation
//other operations
delete obj; //explicitly destroy
}

Destruct with a pointer to object

If an object exists as such:
MyClass obj;
To call a member function:
obj.myMemberFunction();
Then to call the destructor of that object after it fulfills its purpose:
delete obj;
However, lets say I have a pointer to an object:
MyClass* obj;
To call a member function:
obj->myMemberFunction();
Now... How do I call the destructor on this object?
You've got it backwards; do delete in the second case and not the first:
MyClass obj;
obj.myMemberFunction();
//delete obj;
//^^^^^^^^^^^
// NO! `obj` has automatic storage and will
// be destroyed automatically when it goes out
// of scope.
delete expects a pointer to a dynamically-allocated object:
MyClass* obj = new MyClass;
obj->myMemberFunction();
delete obj;
If you create it with
MyClass obj;
you do nothing to delete it. If you create it with
MyClass* obj = new MyClass();
you use
delete obj;
to delete it.
The operator delete is intended to be used with pointers that stores the adresses of areas allocated on the heap thanks to the corresponding operator new.
void function ()
{
int * pt;
pt = new int;
*pt = 42;
delete pt; // memory released
}
Memory allocated on the stack is automaticly released at the end of the corresponding scope :
void function ()
{
int i;
i = 42;
} // memory released
When you write MyClass obj;, the object is allocated on the stack, as opposed to on the heap. In this case, the object is destroyed automatically then it goes out of scope. The compiler generates code to ensure the destructor is called. So you don't delete the object explicitly.
delete is used when an object is allocated on the heap. For example:
MyClass* pobj = new MyClass;
// Do something with pobj...
delete pobj;

Overriding function in C++ doesn't work

#include <cstdio>
using namespace std;
class A {
public:
virtual void func() { printf("A::func()"); }
};
class B : public A {
public:
virtual void func() { printf("B::func()"); }
};
int main() {
A a = *(A *)new B();
a.func();
}
The question is simple: why a->func() calls function in class A even though a contains object of class B?
A a = *(A *)new B();
a.func();
Here's what happens in this code, step by step:
new B(): a new object of type B is allocated on the free store, resulting in its address
(A*): the address of the object is cast to A*, so we have a pointer of type A* actually pointing to an object of type B, which is valid. All OK.
A a: here the problems start. A new local object of type A is created on the stack and constructed using the copy constructor A::A(const A&), with the first paremeter being the object created before.
The pointer to the original object of type B is lost after this statement, resulting in a memory leak, since it was allocated on the free store with new.
a.func() - the method is called on the (local) object of class A.
If you change the code to:
A& a = *( A*) new B();
a.func();
then only one object will be constructed, its pointer will be converted to pointer of type A*, then dereferenced and a new reference will be initialized with this address. The call of the virtual function will then be dynamically resolved to B::func().
But remember, that you'd still need to free the object since it was allocated with new:
delete &a;
Which, by the way, will only be correct if A has a virtual destructor, which is required that B::~B() (which luckily is empty here, but it doesn't need to in the general case) will also be called. If A doesn't have a virtual destructor, then you'd need to free it by:
delete (B*)&a;
If you would want to use a pointer, then that's the same as with the reference. Code:
A* a = new B(); // actually you don't need an explicit cast here.
a->func();
delete (B*)a; // or just delete a; if A has a virtual destructor.
Now that you've modified your code snippet, the problem is clear. Polymorphism (i.e. virtual functions) are only invoked via pointers and references. You have neither of these. A a = XXX does not contain an object of type B, it contains an object of type A. You've "sliced away" the B-ness of the object by doing that pointer cast and dereference.
If you do A *a = new B();, then you will get the expected behaviour.
The problem you encounter is classic object slicing :
A a = *(A *)new B();
Make a either a reference or pointer to A, and virtual dispatch will work as you expect. See this other question for more explanations.
You commented on another answer that "Compiler should at least give warning or what". This is why is it considered a good practice to make base classes either abstract of non copyable : your initial code wouldn't have compiled in the first place.
This might do that trick.
A &a = *(A *)new B();
a.func();
Or
A *a = new B();
a->func();
Virtual dispatch works only with pointer or reference types:
#include <cstdio>
using namespace std;
class A {
public:
virtual void func() { printf("A::func()"); }
};
class B : public A {
public:
virtual void func() { printf("B::func()"); }
};
int main() {
A* a = new B();
a->func();
}
The problem is the deference and casting of B to A with the A a = *(A *)new B();
You can fix it with just removing the *(A *) changing it to (A *a = new B(); ) but I would take it a step further since your variable name is not good for instantiation of B.
It should be
B *b = new B();
b->func();
Because you performed slicing when you copied the dynamically allocated object into object a of type A (which also gave you a memory leak).
a should be a reference (A&) instead, or just keep the pointer.