class Base
{
private:
int nID;
friend int fnDeleteBase(Base* base);
public:
Base( int baseID):nID(baseID) { cout << "Base Constructed with value" << endl; }
Base () : nID(5){cout << "Base Constructed WITHOUT value" << endl; }
~Base() { cout << "Base class object killed " << endl; }
};
int fnDeleteBase(Base* base) // Line 1
{
delete base; // Line 2 - important
cout << "Base object deleted " << endl;
return (1);
}
int main()
{
Base aBase; // Line 3
try
{
int i = fnDeleteBase(&aBase); // Line 4
}
catch(...)
{
cout << "Exception handled " << endl;
}
return (0);
}
The above code snippet I was debugging. I am unable to Step into at Line 2 where I am deleting the base object. as soon as I try to step into or run over the line 2, the control goes and I have to kill the debugging or execution
The output I get is:
Base Constructed (any of the construction is valid)
Base class Object killed
However everything works fine and if Line 3 is changed to Base * aBase = new Base();. The output on console is:
Base Constructed (any of the construction is valid)
Base class Object killed
Base object Deleted
Can somebody share the technical details behind the two?
You should only use delete on pointers that were constructed using new (or pointers that were assigned to other pointers that were constructed using new), no exceptions (that I know of).
Using delete on anything else (which is what happens in the first case, since the parameter of fnDeleteBase is a pointer to Base aBase, which is not a pointer and there is no new keyword there) results in undefined behaviour.
Explaining what exactly the compiler does won't really be helpful as, with undefined behaviour, this can differ from compiler to compiler. And it should be avoided at all costs.
Related
I'd like to compare two objects by their class name. The first object is of type Card* which points to a MagicCard object, and the second is of type MagicCard - a child class of Card. When I compare them with typeid it doesn't work:
if (typeid(*(this->cards[index])) != typeid(card)) {
//the first object is of type Card* inside a vector and points to a
MagicCard object
//card is of type MagicCard
return false;
//this "if" check stops the method in case the types are different.
}
The comparison above should return that the objects are of the same type, because the the element in that position inside the vector I know that there is a function getClass() in Java so I am looking for some kind of an equivalent in C++ which compares objects by the derived class, not by the mother class.
EDIT: I changed the code to Peter's suggestion and added information why I need this check. It doesn't work yet.
It's almost always incorrect to be looking at typeid.
You can get a MagicCard * from a Card * with dynamic_cast, and it will be a null pointer if the Card * doesn't point to a MagicCard object.
if (auto * magicCard = dynamic_cast<MagicCard>(cards[index])) {
// do something with magicCard
}
However it is often better to add virtual void doSomething() to Card, and override it in MagicCard.
cards[index]->doSomething(); // no mention of MagicCard needed
It is not clear how your Card and MagicCard classes are declared.
typeid does not work with non-polimorphistic classes according to cppreference.com.
If you, for example got the following program, the output will be as shown in the comments next to the output line:
#include <iostream>
#include <typeinfo>
class BaseNonPoly { };
class DerivedNonPoly : public BaseNonPoly { };
class BasePoly { virtual void foo() {} };
class DerivedPoly : public BasePoly { };
int main()
{
BaseNonPoly baseNonPoly;
DerivedNonPoly derivedNonPoly;
BasePoly basePoly;
DerivedPoly derivedPoly;
BaseNonPoly& pBaseNonPoly = baseNonPoly;
BaseNonPoly& pDerivedNonPoly = derivedNonPoly;
BasePoly& pBasePoly = basePoly;
BasePoly& pDerivedPoly = derivedPoly;
std::cout << "typeid(baseNonPoly)=" << typeid(baseNonPoly).name() << std::endl; // typeid(baseNonPoly)=11BaseNonPoly
std::cout << "typeid(derivedNonPoly)=" << typeid(derivedNonPoly).name() << std::endl; // typeid(derivedNonPoly)=14DerivedNonPoly
std::cout << "typeid(basePoly)=" << typeid(basePoly).name() << std::endl; // typeid(basePoly)=8BasePoly
std::cout << "typeid(derivedPoly)=" << typeid(derivedPoly).name() << std::endl; // typeid(derivedPoly)=11DerivedPoly
std::cout << "typeid(pBaseNonPoly)=" << typeid(pBaseNonPoly).name() << std::endl; // typeid(pBaseNonPoly)=11BaseNonPoly
std::cout << "typeid(pDerivedNonPoly)=" << typeid(pDerivedNonPoly).name() << std::endl; // typeid(pDerivedNonPoly)=11BaseNonPoly
std::cout << "typeid(pBasePoly)=" << typeid(pBasePoly).name() << std::endl; // typeid(pBasePoly)=8BasePoly
std::cout << "typeid(pDerivedPoly)=" << typeid(pDerivedPoly).name() << std::endl; // typeid(pDerivedPoly)=11DerivedPoly
return 0;
}
As you can see, the object of the non-polimorphic derived class DerivedNonPoly without virtual method can not be identified as what it really is and returns the type of it's parent BaseNonPoly instead.
As in Caleth's answer mentioned, it is good practice to avoid special cases depending on concrete derived class types. Since this, however, can't always be avoided in an elegant way, it might be enough to use a unused virtual function or a virtual deconstructor to your Card and MagicCard class for typeid to work correctly.
I have created an object of a class inside a function. The created object is passed as a parameter to another class. I expect that when I exit the function in which the object is created, the object must be destroyed.
Also any references to this object must be invalid, but I find that the object referenced after exiting the function is still valid. Trying to understand the scope of the object. The code snipped is given below.
class TextWidget
{
public:
TextWidget()
{
cout << "Constructor TextWidget" << endl;
}
TextWidget(int id)
{
_ID = id;
cout << "Constructor TextWidget" << endl;
}
~TextWidget()
{
cout << "Destructor TextWidget" << endl;
}
void printWidgetInstance()
{
cout << this << endl;
}
int _ID;
};
class AnotherWidget
{
public:
AnotherWidget()
{
cout << "Constructor AnotherWidget" << endl;
}
~AnotherWidget()
{
cout << "Destructor AnotherWidget" << endl;
}
TextWidget* getTextWidget()
{
return _textWidget;
}
void setTextWidget(TextWidget* t)
{
_textWidget = t;
}
int getTextID() { return _textWidget->_ID; }
private:
TextWidget* _textWidget;
};
ButtonWidget b;
AnotherWidget a;
void fun()
{
TextWidget t(7);
b.setTextWidget(&t);
a.setTextWidget(&t);
a.getTextWidget()->printWidgetInstance();
b.getTextWidget()->printWidgetInstance();
}
int main()
{
fun();
cout << "TextWidget in AnotherWidget is ";
a.getTextWidget()->printWidgetInstance();
cout << "Text ID in a is " << a.getTextID() << endl;
getchar();
return 0;
}
OUTPUT
Constructor AnotherWidget
Constructor TextWidget
Before deleting TextWidget in class ButtonWidget 0x73fdf0
Before deleting TextWidget in class AnotherWidget 0x73fdf0
0x73fdf0
0x73fdf0
Destructor TextWidget
TextWidget in AnotherWidget is 0x73fdf0
Text ID in a is 7
A variable declared using automatic storage duration (not using new) has a lifetime of its scope. Accessing the variable outside the scope results in undefined behavior.
You need to understand what classes, objects, pointers and references are. Classes are code in memory, this code deals with the member variables. A class does not occupy any data memory. When you create a object you instantiate the class. This step will reserve some data memory for the local data of one object instance of the class. To access this instance you get a reference to the object (this). An object variable holds a pointer to the data memory of an instance of a class.
When an object gets destroyed the occupied memory block gets listed as free but not cleared. So if you still have a reference to that memory block you may access it. And as long as the system doesnt use this memory block for other purposes you still will find your bits and bytes there.
You may declare some variables:
long long_array[10];
myclass myobject;
These variables are stored sequential in one memory block. When you now access the memory behind the long_array through that array:
long_array[10] = 12345; // valid range is from long_array[0] to long_array[9]
Than you will overwrite the data of the object myobject.
Assume we have (in C++): MyClass* x = new MyClass(10)
Can someone please explain what 'exactly' happens when compiler parses this statement? (I tried taking a look at the Red Dragon book but couldn't find anything useful).
I want to know what happens in the stack/heap or compiler's symbol table. How compiler keeps track of the type of x variable? How later calls to x->method1(1,2) will be resolved to appropriate methods in MyClass (for simplicity assume there is no inheritance and MyClass is the only class that we have).
MyClass* x is a definition of pointer to object (instance) of type MyClass. Memory for that variable is allocated according to the place of its definition: if it is defined in the method, and is a local variable, stack is used. And it is memory to store the address.
Then expression new MyClass(10) is a command to allocate memory in heap for an object (instance) itself and return address to be stored in x. To fill the memory of new object MyClass (set up its initial state) special method (at least one) is executed automatically - constructor (or several in some cases) - that receives value 10 in your example.
Because C++ allows inheritance (this is also the reason for the execution of several constructors when an instance created) there are some mechanism to determine which method should be exactly called. You should read somewhere about Virtual method table.
In the simplest case (without inheritance), type of variable x (pointer to object of type MyClass) provide all necessary information about object structure. So, x->method1(1,2) or (*x).method1(1,2) provide call of member method1 to execute it with parameters 1 and 2 (stored in stack) as well as with data that form the state of object (stored in heap) and available by this pointer inside any non-static member of class. The method itself, of course, not stored in the heap.
UPDATE:
You can make example to make same experiments, like:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
private:
int innerData;
long long int lastValue;
public:
MyClass() // default constructor
{
cout << "default constructor" << endl;
innerData = 42;
lastValue = 0;
}
MyClass(int data) // constructor with parameter
{
cout << "constructor with parameter" << endl;
innerData = data;
lastValue = 0;
}
int method1(int factor, int coefficient)
{
cout << "Address in this-pinter " << this << endl;
cout << "Address of innerData " << &innerData << endl;
cout << "Address of lastValue " << &lastValue << endl;
cout << "Address of factor " << &factor << endl;
lastValue = factor * innerData + coefficient;
return lastValue;
}
};
int main(void)
{
MyClass* x = new MyClass(10);
cout << "addres of object " << x << endl;
cout << "addres of pointer " << &x << endl;
cout << "size of object " << sizeof(MyClass) << endl;
cout << "size of pointer " << sizeof(x) << endl;
x->method1(1, 2);
}
C++ is indeed a bit nasty, and this already started in C. Just look at the first 3 tokens : MyClass * x. The compiler has to look up MyClass to determine that this is not a multiplication. Since it is a type, it shouldn't look up x either, but add x to the symbol table right there (really can't be delayed). In the ideal world of simple-to-parse languages, there would be no need to keep the symbol table up to date for every token parsed.
After the definition of x, the = signals an initializing expression. That's an easy one to parse: new is unambiguously a keyword, it's not a placement new and the type being created is right there.
I have a class, let's call it A. There are two subclasses of class A which are a and b.
I'm making a pointer of class A like this:
A *pointer;
At some point in the program I initialize the pointer like this:
pointer = new a();
At some other point, I run a function of class A:
pointer->function(&pointer);
This function is inside class A (so all subclasses have it). There is a chance that when this function is called, I want to change pointer to another subclass, here is what I tried:
void A::function(A **pointer)
{
if (something)
{
delete *pointer;
*pointer = new b();
}
}
Although this works, I'm really curious if this is good practice, I'm calling delete from inside the object and freeing the object itself, could this be undefined behavior and I got lucky it worked? Am I not understanding this right? Am I making this more complicated than it should be?
Yes, that's valid as long as you are careful. See more discussion at a question specifically about delete this.
However, as with other things in C++ which are valid as long as you are careful, you are better to find another solution that will be less prone to errors. I suggest you reworking you code into a function returning a new pointer, and having the old one automatically destroyed (via a smart pointer, for example).
Something along the lines:
struct A {
static std::shared_ptr<A> function(std::shared_ptr<A>& ptr, int x) {
if (x > 0)
return std::make_shared<A>(x);
else return ptr;
}
A(int _x): x(_x) {}
int x;
};
Note also I made function() to be static, as it anyway accepts the object as its first argument. See live on coliru.
In fact, I don't quite like this solution with shared_ptr, and if someone will give a better implementation of this approach, I'll be glad to know.
This code is valid ( for more information about correctness see this answer ).
But it's not a good practice, because other developer can miss nuance, that using one of member functions will lead to reconstruction of object.
It's better to explicitly reconstruct object than hide it in member function.
Or just use smart pointers.
As a design I don't like that a pointer suddenly points to another object (of a different type) when it is not clear that it happens. It could be argued that since OPs code passes &pointer it indicates that it may change. However, I prefer an assignment instead - I think that is more clear.
I would try something like this:
int uglyGlobal = 1; // don't try this at home... ;-)
class A
{
public:
int n;
A() {n = uglyGlobal++; cout << "A cons for #" << n << endl;}
virtual ~A() {cout << "A des for #" << n << endl;}
unique_ptr<A> function(int something, unique_ptr<A> ptr);
};
class a : public A
{
public:
a() {cout << "a cons" << endl;}
~a() override {cout << "a des" << endl;}
};
class b : public A
{
public:
b() {cout << "b cons" << endl;}
~b() override {cout << "b des" << endl;}
};
unique_ptr<A> A::function(int something, unique_ptr<A> ptr)
{
if (something == 0)
{
// Turn it into an A
return unique_ptr<A>(new A);
}
else if (something == 1)
{
// Turn it into an a
return unique_ptr<A>(new a);
}
else if (something == 2)
{
// Turn it into an b
return unique_ptr<A>(new b);
}
else
// Keep the current
return ptr;
}
int main()
{
cout << "Make A" << endl;
unique_ptr<A> x (new A);
cout << "1. call - turn A into a" << endl;
x = x->function(1, move(x));
cout << "2. call - turn a into b" << endl;
x = x->function(2, move(x));
cout << "3. call - turn b into another b" << endl;
x = x->function(2, move(x));
cout << "4. call - keep current b" << endl;
x = x->function(3, move(x));
cout << "Return from main" << endl;
return 0;
}
The output is:
Make A
A cons for #1
1. call - turn A into a
A cons for #2
a cons
A des for #1
2. call - turn a into b
A cons for #3
b cons
a des
A des for #2
3. call - turn b into another b
A cons for #4
b cons
b des
A des for #3
4. call - keep current b
Return from main
b des
A des for #4
In general, You must ensure that every execution path that call function doesn't have a stack frame for a method of A or derived class (this is invalid).
So, it is dangerous. In MFC api programming, this happens "normally" in the WM_NCDESTROY message handler. In it you do thing like delete this, but Windows ensure that WM_NCDESTROY is the last message sent to a window.
I suggest you to change a little the api of class A and use unique_ptr to handle the memory:
#include <memory>
class A
{
public:
std::unique_ptr<A> f()
{
return std::make_unique<A>();
}
};
int main()
{
auto p = std::make_unique<A>();
p = std::move(p->f());
return 0;
}
In this way, you move the destruction from inside f() to the assignment of p.
In the below code, when I pass an unnamed A variable to the ctor of B, the variable is destructed after the line. According to this answer :
Temporary objects are destroyed at the
end of the full expression they're
part of. A full expression is an
expression that isn't a sub-expression
of some other expression. Usually this
means it ends at the ; (or ) for if, while, switch etc.)denoting the end
of the statement.
I get it but how can the class B know the value of its mamber_a variable, after it is destructed? I know that copy ctor of A is enver called. How is this possible?
#include <iostream>
using namespace std;
class A
{
int sign;
A();
const A & operator=(const A &);
public:
A(int x) : sign(x) {
cout << "A ctor : " << sign << endl;
}
void WriteA() const {
cout << sign << endl;
}
~A() {
cout << "A dtor : " << sign << endl;
}
A(const A &) {
cout << "A copied : " << sign << endl;
}
};
class B
{
int sign;
const A & member_a;
public:
B(const A & aa , int ww ) : sign (ww) ,member_a(aa) {
cout << "B ctor : " << sign << endl;
}
void WriteB() const {
cout << "Value of member_a :";
member_a.WriteA();
}
~B() {
cout << "B dtor : " << sign << endl;
}
};
int main() {
A a(10);
B b1(a,1);
b1.WriteB();
B b2(A(20),2);
b2.WriteB();
return 0;
}
The output is :
A ctor : 10
B ctor : 1
Value of member_a :10
A ctor : 20
B ctor : 2
A dtor : 20
Value of member_a :20 // Object A was destructed. Where does this 20 come from?
B dtor : 2
B dtor : 1
A dtor : 10
You have one of the tricky parts of C++
It is pure chance that member_a has the value 20. You are hitting what is refereed to as undefined behavior.
When a class retains a reference to an external object it is the responsibility of the programmer to make sure that the lifetime of the object lasts longer than the object being referred to. In this case when you call member_a.WriteA(); the a object has already been destroyed and thus you are accessing memory that may potentially not belong to you (in this case it just happens to be in a location nearby that has not been overridden (completely by chance)).
If you are going to retain a reference to an object. You can retain a const reference but sometimes it is best to make the parameter a normal reference so that you can not accidentally pass a temporary value (this does not always work as you may have to pass a const object by reference).
Using a reference to a destructed object is an "undefined behaviour".
In A's destructor, try setting "sign" to "-1" and see what happens. Odds are the call to "WriteB" will show that you have sent a message to a deceased object.
Now try putting a bunch of stack using code between the constructor of b2 and the call to b2.WriteB, for example a call to a subroutine. You will probably now find that the call prints something different.