Polymorphism: member acces and getter give different results - c++

Here is the code:
#include <iostream>
#include <vector>
#include <array>
class Parent
{
public:
virtual void whatAmI(){std::cout << "A Parent" << std::endl;}
virtual long getValue(){std::cout << "value from Parent " << std::endl; return value;}
long value;
};
class Child : public Parent
{
public:
virtual void whatAmI(){std::cout << "A child" << std::endl;}
virtual long getValue(){std::cout << "value from Child " << std::endl; return value;}
long value;
};
class SomeClass
{
public:
Parent * parent;
};
int main()
{
Child c = Child();
SomeClass sc;
sc.parent = &c;
sc.parent->value = 10;
sc.parent->whatAmI();
std::cout << sc.parent->value << std::endl;
std::cout << sc.parent->getValue() << std::endl;
}
It returns:
A child
10
value from Child
0
I have read about object slicing, and made sure I would assign the value of 10 after the child has been sliced up. I still don't understand why the direct field access and the function call would give different results.
Thank you.

There is no slicing here - you're accessing via a pointer.
The behaviour is due to the fact that member-variable access is not polymorphic. So parent->value always refers to Parent::value, never Child::value. Whereas value (in Child::getValue) refers to Child::value.

Related

Does static_cast makes the compiler allocate more space than what it is meant to by new operator?

I have written a Base class and a Derived class with the respective data members as you could see in the code below. Now in main function I have created new Base class objects pointed by Derived class pointers using static_cast for it.
#include <iostream>
#include <vector>
class Base {
public:
int b;
Base() : b(2){};
int get_b() const;
};
class Derived : public Base {
public:
int d;
Derived() : d(4){};
int get_d() const;
};
int Base::get_b() const { return b; }
int Derived::get_d() const { return d; }
int main() {
std::vector<Derived *> bArray;
bArray.push_back(static_cast<const Derived *>(new Base()));
bArray.push_back(static_cast<const Derived *>(new Base()));
std::vector<Derived *>::iterator bArrayIt = bArray.begin();
for (; bArrayIt != bArray.end(); ++bArrayIt) {
std::cout << (*bArrayIt)->get_b() << std::endl;
std::cout << (*bArrayIt)->get_d() << std::endl;
}
}
Output:
2
0
Now in the code I have tried accessing the data members of the derived class using the Derived pointers but I expected it to return a compilation error or 'ArrayOutOfBoundIndex' or segmentation_fault because the object is of Base type as space is allocated for base object only but instead got value of that member 'd' as zero. According to what I know about static_cast it just alters the pointer type and not allocate memory,but here not only we could access the memory not allocated but the value has been set to 0 initially beforehand, so I did a small experiment of my own.
#include <iostream>
#include <string.h>
class State;
class Base;
class Derived;
class State {
public:
static bool flag;
};
bool State::flag = true;
class Base : public State {
public:
int a;
int b;
int c;
Base() : a(2), b(4), c(16){};
int get_a() { return a; }
int get_b() { return b; }
int get_c() { return c; }
};
class Derived : public Base {
public:
int d;
int e;
int f;
Derived() : d(6), e(8), f(12){};
int set_d(int ds) { d = ds; }
int get_d() { return d; }
int get_e() { return e; }
int get_f() { return f; }
};
int main() {
Derived *d[2];
d[0] = static_cast<Derived *>(new Base());
d[1] = static_cast<Derived *>(new Base());
std::cout << d[0]->get_a() << std::endl;
std::cout << d[0]->get_d() << std::endl;
d[0]->set_d(100);
std::cout << d[0]->get_d() << std::endl;
int *i = reinterpret_cast<int *>(d[0]);
std::cout << (*i) << std::endl;
i++;
std::cout << (*i) << std::endl;
i++;
std::cout << (*i) << std::endl;
i++;
std::cout << (*i) << std::endl;
i++;
std::cout << (*i) << std::endl;
i++;
std::cout << (*i) << std::endl;
std::cout << "Let's move onto d[1]" << std::endl;
int *j = reinterpret_cast<int *>(d[1]);
std::cout << (*j) << std::endl;
j++;
std::cout << (*j) << std::endl;
j++;
std::cout << (*j) << std::endl;
j++;
std::cout << (*j) << std::endl;
j++;
std::cout << (*j) << std::endl;
j++;
std::cout << (*j) << std::endl;
return 0;
}
Output:
2
0
100
2
4
16
100
0
0
Let's move into d[1]
2
4
16
0
0
0
The output was according to what I got before.
My Questions:
Why is the variable allowed to access memory which is not allocated by the new keyword or the compiler and how is it able to do so?
If it is able to access memory location why doesn't the compiler give any runtime error or compile time error and is there any method to make the compiler do so?
Now if the memory is allocated by the compiler or somehow, what implications does it have on the memory i.e. if the Base class is of 12 bytes and the Derived class is of 24 bytes then will every object creation of Base Type and using static_cast for it to be pointed by Derived pointer will allocate 24 bytes of memory?
Why is the variable allowed to access memory which is not allocated by the new keyword or the compiler and how is it able to do so?
Because, there is nothing which will prevent you from doing it. C++ gives a lot of freedom for programmers, but with this freedom comes responsibility (e.g. making sure that you don't access unallocated memory).
If it is able to access memory location why doesn't the compiler give any runtime error or compile time error?
It's Undefined Behaviour, which means, that at runtime your program becomes unpredictable. If you're lucky, it may crash for some reason (e.g. segfault), but it doesn't have to. At compile time, this operation is prefectly legal in terms of language, so there is nothing compiler will complain about. You'll probably have to use some static analysis tool to catch such mistakes.
Now if the memory is allocated by the compiler or somehow, what implications does it have on the memory i.e. if the Base class is of 12 bytes and the Derived class is of 24 bytes then will every object creation of Base Type and using static_cast for it to be pointed by Derived pointer will allocate 24 bytes of memory?
static_cast has nothing to do with memory allocation. It just converts type of pointer. Allocating memory for object is up to operator new and size of memory allocated won't be affected by any pointer conversion.

Why are the parent's methods still alive after child's destruction

I don't understand why the '''execute''' function of the Parent class is run. I feel like there are two instances: one for the parent class, one for the child class, but why? Indeed, this program is printing "1 Parent", as i expected "1 Child" or "0 Parent". If i uncomment the delay line, the output will be "1 Child".
I know there is a race condition in this program. This program was only made to understand the working principle of the inheritance in a multithreaded environment.
Thank you !
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <thread>
class Parent
{
public:
std::thread myThread;
int a;
Parent() {
this->myThread = std::thread();
this->a = 0;
}
void start()
{
this->myThread = std::thread(&Parent::execute, this);
}
virtual void execute() {
std::cout << a << " Parent" << std::endl;
}
virtual ~Parent() {
while(!this->myThread.joinable());
this->myThread.join();
}
};
class Child : public Parent
{
public:
Child() {
this->a = 1;
}
void execute() override {
std::cout << a << " Child" << std::endl;
}
~Child() {
}
};
int main()
{
std::cout << "Init" << std::endl;
Child * chld = new Child();
chld->start();
//std::this_thread::sleep_for(std::chrono::milliseconds(x));
std::cout << "Delete" << std::endl;
delete chld;
return 0;
}
Your program has undefined behavior which means "everything can happen".
You start a new thread which hold a pointer ( this ) to an object. This thread will later call a virtual method which means it needs to use data from the object it points to. The vtable pointer itself is some kind of data of the class. Because you delete your object from the other thread, the pointer ( this ) is simply pointing to a destructed object and accessing data ( vtable ) from an deleted object is undefined behavior.
Your observation is depending on the compiler implementation and maybe also on optimizing level. It is possible, that your compiler rewinds during deconstruction the vtable pointer down to the base class pointer. And as the memory of the object is not overridden from any other content ( which is even undefined! ) you can observe a call to the base function after destruction. But this is nothing you can rely on, as it is not allowed at all to use any object after destruction IF you use data members of the object which here is the vtable pointer.
In a short: Your code contains a bug and everything can happen as it is undefined behavior.
Your code exhibits the Undefined behavior (in your case resulting in Parent::execute call) because of the race condition between thread creation and Child object destruction. To fix it, you can define proper start and stop methods in your Parent class and call stop in Child destructor to prevent it from being destroyed before thread joins.
class Parent
{
public:
Parent(): myThread_() {
std::cout << "Parent CTor" << std::endl;
}
virtual ~Parent() = default;
bool start()
{
std::cout << "start" << std::endl;
if (myThread_.joinable()) {
std::cout << "already started" << std::endl;
return false;
}
myThread_ = std::thread([this]() {
execute();
});
return true;
}
bool stop() {
std::cout << "stop" << std::endl;
if (!myThread_.joinable()) {
std::cout << "not started" << std::endl;
return false;
}
myThread_.join();
return true;
}
virtual void execute() = 0;
private:
std::thread myThread_;
};
class Child : public Parent
{
public:
Child() {
std::cout << "Child CTor" << std::endl;
}
~Child() override {
stop();
}
void execute() override {
std::cout << "Child::execute()" << std::endl;
}
};
int main()
{
std::cout << "Init" << std::endl;
Child * chld = new Child();
chld->start();
std::cout << "Delete" << std::endl;
delete chld;
return 0;
}
I defined Parent::execute as abstract because probably you don't want it to be called at all and in case of another bug, at least you can get
terminate, pure virtual method called
This is nothing whatsoever to do with threads. You can reproduce the whole thing - including Undefined Behaviour - synchronously.
Single-threaded version of your classes:
#include <iostream>
#include <string>
class Parent
{
public:
int a;
Parent() : a(0) {}
virtual ~Parent() {}
virtual void execute() {
std::cout << a << " Parent" << std::endl;
}
};
class Child : public Parent
{
public:
Child() {
a = 1;
}
void execute() override {
std::cout << a << " Child" << std::endl;
}
};
and the single-threaded test cases demonstrating exactly the same behaviour:
int main()
{
Child c;
std::cout << "=== automatic lifetime ===\n";
std::cout << "virtual dispatch: ";
c.execute();
std::cout << "explicit static dispatch: ";
c.Parent::execute();
std::cout << "=== dynamic lifetime ===\n";
Child *pc = new Child;
std::cout << "virtual dispatch: ";
pc->execute();
std::cout << "explicit static dispatch: ";
pc->Parent::execute();
std::cout << "=== undefined behaviour ===\n";
delete pc;
std::cout << "explicit static dispatch: ";
pc->Parent::execute();
std::cout << "virtual dispatch: ";
pc->execute();
}
The last two output statements are swapped, because the last one crashed when I ran it (the penultimate is still UB, but happened not to crash)
=== automatic lifetime ===
virtual dispatch: 1 Child
explicit static dispatch: 1 Parent
=== dynamic lifetime ===
virtual dispatch: 1 Child
explicit static dispatch: 1 Parent
=== undefined behaviour ===
explicit static dispatch: 1 Parent
Segmentation fault (core dumped) ./a.out

Object not constructed and related typeid information

#include <iostream>
using namespace std;
class Base {
public:
~Base() {
static int count = 0;
cout << "...calling destructor " << ++count << endl;
}
};
#include <typeinfo>
int main () {
Base b0;
Base b1 = Base();
Base b2();
cout << typeid(b1).name() << endl;
cout << typeid(b2).name() << " : " << b2 << endl;
return 0;
}
OUTPUT
4Base
F4BasevE : 1
...calling destructor 1
...calling destructor 2
In the above code, I am expecting to create three objects of type Base which has no user-defined constructors.
As is obvious in the output, the destructor is invoked only twice. Inspecting object b2 using typeid, emits the strange F4BasevE string (as opposed to 4Base).
Questions:
What does F4BasevE mean?
1 appear when trying to print b2 - what does that mean?
What constructor do I have to define in the class to be able to
create object b2 the way it is defined?

unique_ptr does not call the destructor to free the pointer

I am passing unique_ptr to function and then move the pointer to another unique_ptr, all is working fine as need, but while point is unique_ptr does not call destructor of the when it goes out of scope.
Below is my code. and its output, the code is in eclipse.
#include <iostream>
#include <memory>
using namespace std;
class BaseCcExpander;
class DeriveHandler;
class ExpansionRuleExecuter;
class DeriveType1;
class ParamBase
{
public :
ParamBase()
{
std::cout << "Ctor:ParamBase:\n";
}
std::unique_ptr<ExpansionRuleExecuter> paramexpander;
virtual ~ParamBase() { std::cout << "Dtor::~ParamBase:\n"; }
virtual void attachBase(int paramGrp,int paramId,std::unique_ptr<ExpansionRuleExecuter> xbaseExpander);
};
ParamBase* obj;
void ParamBase::attachBase(int paramGrp,int paramId,std::unique_ptr<ExpansionRuleExecuter> xbaseExpander)
{
std::cout << "In: ParamBase::attachHandler :\n";
paramexpander = std::move(xbaseExpander);
}
class ExpansionRuleExecuter
{
public:
ExpansionRuleExecuter()
{
std::cout << "Ctor ExpansionRuleExecuter::ExpansionRuleExecuter:\n" << endl;
}
virtual ~ExpansionRuleExecuter(){
std::cout << "Dtor ~ExpansionRuleExecuter::ExpansionRuleExecuter:\n" << endl;
}
virtual void handleExpansion() = 0;
};
class DeriveHandler : public ExpansionRuleExecuter
{
public:
DeriveHandler()
{
std::cout << "Ctor::DeriveHandler:\n" << endl;
}
~DeriveHandler()
{
std::cout << "Dtor::~DeriveHandler:\n" << endl;
}
void handleExpansion()
{
std::cout << "DeriveHandler expanded\n" << endl;
}
};
ParamBase *obj1;
class BaseCcExpander
{
public:
BaseCcExpander()
{
std::cout << "Ctor::BaseCcExpander:\n" << endl;
}
virtual ~BaseCcExpander()
{
std::cout << "Dtor::~BaseCcExpander:\n" << endl;
}
typedef unique_ptr<ExpansionRuleExecuter> ccHandler;
BaseCcExpander::ccHandler ccBaseHandler;
void attachHandler(int paramGrp, int paramId,std::unique_ptr<ExpansionRuleExecuter> xhandler)
{
std::cout << "BaseCcExpander::attachHandler:\n" << endl;
obj1->attachBase(paramGrp,paramId,std::move(xhandler));
}
};
class DeriveType1 : public ParamBase
{
public :
DeriveType1() { std::cout << "Ctor: DeriveType--------1:\n" << endl;}
~DeriveType1() { std::cout << "Dtor::~DeriveType---------1\n" << endl;}
void attachBase(std::unique_ptr<ExpansionRuleExecuter> xbaseExpander);
};
BaseCcExpander ccexpander;
int main()
{
obj1 = new(DeriveType1);
ccexpander.attachHandler(1,2,std::unique_ptr<ExpansionRuleExecuter>(new DeriveHandler));
if(obj1->paramexpander.get())
{
ExpansionRuleExecuter *expand = obj1->paramexpander.get();
expand->handleExpansion();
}
}
You wrote in a comment:
but by is obj1 not destroying even after the program is over as its in the global space, it should destroy.
There is some misunderstanding here. obj1 is destroyed but the object it points to is not deleted when obj1 is destroyed. If the compiler did that, you won't be able to use:
int main()
{
int i = 10;
int* ip = &i;
// You don't want the run time to call the equivalent of
// delete ip;
// when the function returns. That will lead to undefined behavior
// since ip does not point to memory allocated from the heap.
}
When the program ends, the OS reclaims the memory used by the program but that does not mean that it calls the destructor of obj1.
Had the destructor been responsible for releasing resources other than memory, such as network connections, locks on shared files/folders, etc., they will not be released when the program ends without the destructor getting called.
Your variable pointed by obj1 is not deleted, hence its members would not be destroyed until the delete happens and the unique_ptr will remain alive then the destructor will never be called.
You should either call delete on obj1 at the end of your program or use an unique_ptr on it.

Casting base class to derived through std iterator in C++

in my program I have base GeneralHeader, MacHeader that derived from GeneralHeader and NetworkPacket with member Headers that is std list of GeneralHeader:
//Packet.h
enum HeaderType_t {General_Header_type, MAC_Header_type};
class GeneralHeader {
public:
bool Valid;
HeaderType_t HeaderType;
void PrintMe();
};
struct MACHeader: public GeneralHeader {
long unsigned DestAddr:48;
long unsigned SourceAddr:48;
void PrintMe();
};
struct Packet_t {
list<GeneralHeader> Headers;//TODO GeneralHeader
list<GeneralHeader>::iterator it_Header; //TODO GeneralHeader
void PrintMe();
};
While implementing the PrintMe() of Packet_t, that supposed to print all Headers according to HeaderType: if there is a GeneralHeader - it will use GeneralHeader.PrintMe() and if it is MACHeader in the list - it will print MACHeader.PrintMe())
I'm struggling to cast it_Header iterator from base GeneralHeader to derived MACHeader inside Packet_t method PrintMe():
//Packet.cpp
void GeneralHeader::PrintMe() {
std::cout << "Valid " << GeneralHeader::Valid << endl;
std::cout << "Header Type " << GeneralHeader::HeaderType << endl;
};
void HW_MACHeader::PrintMe() {
std::cout << "------------------------ " << endl;
std::cout << "---- MAC HEADER --- " << endl;
std::cout << "------------------------ " << endl;
GeneralHeader::PrintMe();
};
void NetworkPacket_t::PrintMe() {
std::cout << "Valid Packet " << NetworkPacket_t::ValidPacket << endl;
for (it_Header = Headers.begin(); it_Header != Headers.end(); it_Header++) {
switch (it_Header->HeaderType) {
case MAC_Header_type:
static_cast<HW_MACHeader*>(it_Header)->PrintMe();
break;
default:
std::cout << "default" << endl;
};
it_Header++;
};
};
The error: invalid static_cast from type 'std::_List_iterator' to type 'MACHeader*'
Thank you for any help.
The desired/normal polymorphic way would be:
Redefine PrintMe() to a virtual function so that cast is not necessary:
class GeneralHeader {
public:
bool Valid;
HeaderType_t HeaderType;
virtual void PrintMe();
};
class MACHeader: public GeneralHeader {
long unsigned DestAddr:48;
long unsigned SourceAddr:48;
public:
void PrintMe();
};
Also use vector of pointers to GeneralHeader:
list<GeneralHeader*>::iterator it_Header;
Then you can:
(*it_Header)->printMe();
The for loop will be simpler:
for (it_Header = Headers.begin(); it_Header != Headers.end();++it_Header)
(*it_Header)->PrintMe();
I don't know why you need the it_Header to be a member of the class? Can't it just be local to the loop?
You need to dereference it_Header to access the "underlying" object to address the compiler error :
static_cast<HW_MACHeader*>(*it_Header)->PrintMe();
Hoever, that will not solve your problem: you have a list of GeneralHeader; therefore because you want to downcast to an instance of HW_MACHeader, you need to use dynamic_cast; this has to be done either on a reference or a pointer:
dynamic_cast<HW_MACHeader&>(*it_Header).PrintMe();
The line above takes the object "referenced" by it_Header, and tells the compiler to cast it dynamically to a reference of type HW_MACHeader.
Note that dynamic_cast will return a null pointer if it cannot cast down to the type you want.
However, this is not a proper way to do this. You should follow user2672165's advice, and use virtual functions.