Polymorphism/inheritance issue with virtual class member function - c++

I might have the wrong idea on exactly what polymorphism versus inheritance is, but basically what I'm trying to do is have classB derive from classA, and create a classB which overrides a pure virtual member function of classA, like so:
classA:
/////////////////
// CodeBlock.h //
/////////////////
typedef enum {
CCBT_UNDEFINED,
CCBT_FUNCTION,
//...
} CODE_BLOCK_TYPE;
class CCodeBlock {
public:
CCodeBlock::CCodeBlock();
CCodeBlock::CCodeBlock(CString& source, DWORD startPos);
CCodeBlock::~CCodeBlock();
virtual CODE_BLOCK_TYPE CCodeBlock::GetType() = 0
CString m_code;
DWORD m_startPos;
DWORD m_length;
int m_numLines;
}
///////////////////
// CodeBlock.cpp //
///////////////////
//...
CCodeBlock::CCodeBlock(CString& source, DWORD startPos) : m_code(source), m_startPos(startPos) {
m_length = m_code.GetLength();
}
CODE_BLOCK_TYPE CCodeBlock::GetType() {
return CCBT_UNDEFINED;
}
classB:
/////////////////////
// FunctionBlock.h //
/////////////////////
#include "CodeBlock.h"
class CFunctionBlock : public CCodeBlock {
public:
CFunctionBlock::CFunctionBlock();
CFunctionBlock::CFunctionBlock(CString& source, DWORD startPos);
CFunctionBlock::~CFunctionBlock();
CODE_BLOCK_TYPE CFunctionBlock::GetType();
}
///////////////////////
// FunctionBlock.cpp //
///////////////////////
//...
CFunctionBlock::CFunctionBlock(CString& source, DWORD startPos)
{
m_code = source;
m_startPos = startPos;
}
CFunctionBlock::~CFunctionBlock()
{
CCodeBlock::~CCodeBlock();
}
CODE_BLOCK_TYPE CFunctionBlock::GetType()
{
//////////////////////////////
// >> NEVER GETS CALLED! << //
//////////////////////////////
return CCBT_FUNCTION;
}
main:
CCodeBlock *block = new CFunctionBlock(L"function hello(){ print('hello') }", iPos)
CODE_BLOCK_TYPE type = block->GetType(); // ALWAYS RETURNS CCBT_UNDEFINED!
As you can see, GetType() always returns CCBT_UNDEFINED. Keep in mind that CCodeBlock is meant to be a 'generic' version of CFunctionBlock (as well as a few other like-minded classes, some of which contain a CCodeBlock 'm_parent' member variable), and is supposed to inherit any CCodeBlock member variables & member functions, as well as override a specific list of functions contained in CCodeBlock.
How can this be achieved? Would I need to resort to using templates (if that's even possible)?

Bring comment as answer:
you don't need CCodeBlock:: when you declare member functions inside class CCodeBlock

There are several things wrong with your code. Member declarations should not have the class name as qualification (i.e. CCodeBlock:: should be removed from the declarations). Leaving it there makes the code ill formed.
Besides that, the destructor of a derived type will implicitly call the base class' destructor, and you should not do it. If you call it manually, the base subobject will be destroyed twice, probably causing undefined behavior (if the base destructor is not trivial).
Now the particular issue with your code in main was probably more like this:
CCodeBlock *block
= new CFunctionBlock(L"function hello(){ print('hello') }", iPos)
CODE_BLOCK_TYPE type = block->CCodeBlock::GetType();
// ^^^^^^^^^^^^
In C++, qualifying a function call disables dynamic dispatch. The expression block->GetType() will be dispatched to the final overrider of the dynamic type of the object that the block pointer points to. But if you add the qualification: block->CCodeBlock::GetType() you are asking the compiler to call the overrider at the CCodeBlock level.

Related

Overload -> arrow operator in shared_ptr<interface> instance with no pure virtual destructor in interface

I'm trying to overload the -> operator to eventually execute something along the lines:
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle(); //this works wonderfully
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
//the next line doesn't compile, I would like to achieve something like this, but even
//sharedPtrWrapper.get()->Toggle();
//would be nice to achieve, is this possible?
sharedPtrWrapper->Toggle();
//this works:
sharedPtrWrapper->operator->()->Toggle();
Note: I have no control over MyInterface, cannot implement the pure virtual destructor.
Here is what I tried (the below code runs):
#import <memory>
#import <iostream>
struct MyInterface {
virtual bool Toggle() = 0;
};
class A : public MyInterface {
public:
bool Toggle() {
stateEnabled = !stateEnabled;
std::cout<<"current state " << stateEnabled << std::endl;
return true;
}
private:
bool stateEnabled = false;
};
template <typename T>
class Wrapper {
private:
T *unsafePointer = nullptr;
public:
Wrapper<T>()
{ }
T *operator->() const {
return unsafePointer;
}
T *getInner() {
return unsafePointer;
}
Wrapper<T>(T *stuff) {
unsafePointer = stuff;
}
~Wrapper<T>() {}
};
int main(int argc, const char * argv[]) {
MyInterface *myInstance = (MyInterface *)(new A());
myInstance->Toggle();
Wrapper<MyInterface> wrapperS(myInstance);
wrapperS->Toggle();
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(myInstance);
sharedPtrWrapper->operator->()->Toggle();
sharedPtrWrapper.operator->()->operator->()->Toggle();
sharedPtrWrapper.get()->operator->()->Toggle();
(*sharedPtrWrapper).operator->()->Toggle();
return 0;
}
Output:
current state 1
current state 0
current state 1
current state 0
current state 1
current state 0
Program ended with exit code: 0
To reiterate:
This code doesn't compile:
sharedPtrWrapper->Toggle();
How to make it compile?
Edit : I'm using a wrapper because I have no control over the MyInterface, I get it from a library, also shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>(myInstance); doesn't compile, because of the missing pure virtual destructor from the above mentioned interface.
Edit2: Example library usage in pseudocode:
void firstcallbackFromLib(Framework *framework) {
MyInterface *myInstance = framework->getInstance();
{
Wrapper<MyInterface> wrapperS(myInstance);
std::shared_ptr<Wrapper<MyInterface>> sharedPtrWrapper = std::make_shared<Wrapper<MyInterface>>(wrapperS);
//assign sharedPtrWrapper and framework to static instances
}
}
void myFunction() {
sharedPtrWrapper->Toggle(); //this doesn't work, this is what i'm trying to achieve
sharedPtrWrapper->operator->()->Toggle(); //this ugly thing works
}
void lastUninitCallbackFromLibrary() {
MyInterface *p = sharedPtrWrapper.get()->getInner();
framework->releaseInterface(p);
//etc
}
The problem is, that shared_ptr behaves like a pointer and Wrapper does that as well. In summary, you have code that behaves like a pointer to a pointer. In short, you could call (*sharedPtrWrapper)->Toggle(); instead of the abomination sharedPtrWrapper->operator->()->Toggle();.
Careful though: It's unclear what all this is supposed to achieve, because the example code is just an abstraction of your actual code. So, maybe it would just be more elegant to put a forwarding Toggle() method into class Wrapper, but that's impossible to tell with the info provided here.
I am confused about the question. Why wrapper class that does nothing?
If you want to put a class inside shared pointer yet do something uncommon at destruction: like, calling dll's function that performs the destruction, do some preprocessing, perform file closure instead of delete, or do nothing at all if that's what you want. Then you can simply specify it at shared pointer instantiation:
https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr - see construction option 5.
You don't need your wrapper at all.
shared_ptr<MyInterface> mySharedPointer = std::make_shared<MyInterface>();
wont work because MyInterface is an abstract class. But, just like you can do
MyInterface *myInstance = new A();
To have a MyInterface * that points to a concrete derived object, you can use
std::shared_ptr<MyInterface> sharedPtr = std::make_shared<A>();
To get a std::shared_ptr<MyInterface> that points to a concrete derived object. You can then use sharedPtr to access Toggle like
sharedPtr->Toggle();
You can see that working in this live example
sharedPtrWrapper->Toggle(); doesn't compile because of operator-> chaining rules explained well in this answer. In principle: if your object is NOT a pointer, operator-> is called recursively, if it is a pointer, member access is performed. Now std::shared_ptr has overloaded operator-> to access the raw Wrapper<MyInterface>* pointer kept inside and when it is applied on it, it tries to access Toggle, which does not exist.
For clarity note that this code also will not compile:
Wrapper<MyInterface>* wrapper = new Wrapper<MyInterface>(myInstance);
wrapper->Toggle();
You can do this however:
(*sharedPtrWrapper)->Toggle();
Use:
struct CleanupMyInterface {
SomeTypeFromLib* somePointerFromLib = nullptr;
void operator()( MyInterface* ptr ) const {
if (somePointerFromLib && ptr)
somePointerFromLib->releaseInterface(ptr);
}
};
std::shared_ptr<MyInterface> sharedPtr( CreateAnInstanceOfAFromLibrary(), CleanupMyInterface{somePointerFromLib} );
shared_ptr has type-erased destruction, there is no need for a virtual destructor.

Avoid use of undefined object in c++

If I create a class in c++, it is possible to call a function of an object of this class, even if this class does not exists.
For example:
Class:
class ExampleClass
{
private:
double m_data;
public:
void readSomeData(double param)
{
m_data = param;
}
}
Any function where this class is used:
int main()
{
ExampleClass* myClass;
myClass->readSomeData(2.5);
}
Ofcourse this wouldn't function, because myClass is not defined.
To avoid such situations, I check if ExampleClass objects are a null_ptr
example:
void readSomeData(double param)
{
if(this == null_ptr)
return;
m_data = param;
}
But gcc says:
'this' pointer cannot be null in well-defined C++ code; comparison may
be assumed to always avaluate to false.
Ofcourse that is only a warning, but I think it is not nice to have this warning. Is there a better way to check if the pointer of a class is defined?
Testing it in the class is the wrong way, the warning is correct about that if your code is well defined then this must not be null, so the test should happen at the time when you call the member function:
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
if (myClass != nullptr) {
myClass->readSomeData(2.5);
}
return 0;
}
If a pointer must not be null at a certain part of your code then you should do it according to CppCoreGuideline: I.12: Declare a pointer that must not be null as not_null
Micorosoft provides an Guidelines Support Library that has an implementation for not_null.
Or if possible then don't use pointers at all but std::optional.
So a code setup could look like this:
#include <gsl/gsl>
struct ExampleClass {
void readSomeData(double ){}
};
// now it is clear that myClass must not and can not be null within work_with_class
// it still could hold an invalid pointe, but thats another problem
void work_with_class(gsl::not_null<ExampleClass*> myClass) {
myClass->readSomeData(2.5);
}
int main()
{
ExampleClass* myClass = nullptr; // always initialize a raw pointer to ensure
// that it does not point to a random address
// ....
work_with_class(myClass);
return 0;
}
The best way is not use pointers at all:
int main()
{
ExampleClass myClass;
myClass.readSomeData(2.5);
}
That way there's no need for any check, and in fact, checking this inside the function is moot.
If you need nullability, use std::optional instead.
Either don't use pointers as Bartek Banachewicz has pointed out, or properly initialize and check the pointer:
int main()
{
ExampleClass* myClass= 0;
if (myClass)
myClass->readSomeData(2.5);
return 0;
}
Of course you still have to add the instantiation of the object at some point, otherwise the code is nonsense.

C++ Access violation when passing variable

Heres my problem, if I pass a variable from class A to class B via function, then in class B pass that variable to other functions for testing then it works fine.
But if I pass the variable from A to B then try assigning it to a variable in class B, it gives the error for no reason
//Globals.h
enum TypeofObject { CIRCLE, SQUARE, RECTANGLE, DIAMOND };
//Object.h
#include "Globals.h"
class Object
{
void Update();
private:
TypeofObject currentObject;
CollisionDetection * gameCollision;
};
//Object.cpp
void Object::Update()
{
//Do stuff here
gameCollision -> testCollision(currentObject);
}
//CollisionDetection.h
#include "Globals.h"
class CollisionDetection
{
public:
void testCollision(TypeofObject currentObject);
private:
void checkObjects(TypeofObject currentObject);
TypeofObject currentObject;
}
//CollisionDetection.cpp
void CollisionDetection::testCollision(TypeofObject curObject)
{
currentObject = curObject; //<- If I have this then it gives access violation error
checkObjects(curObject); //<- Passing it from one function to the next works
//fine but I want to assign it to currentObject so
//it doesnt need to be passed
}
I assume the issue here is that Object::gameCollision has not been initialised. The CollisionDetection::testCollision function is called correctly because you can imagine member functions as regular function taking an extra hidden parameter:
void CollisionDetection_testCollision(CollisionDetection *this,
TypeOfObject curObject);
Given your definition, the function will run correctly up until the point where this is accessed:
currentObject = curObject; // this->currentObject = curObject
The line above is trying to set some memory at an offset from the this object. If this is not correctly initialised, the function will fail with an access violation.
I presume that checkObjects(curObject) does not fail because you are not accessing any of the data members of CollisionDetection in that function.

Avoiding C++ polymorphism

I recently created my own scripting language. My code structures are heavily based on polymorphism. (I'm not really sure about how is this called. I've got a virtual function and then I derive the class and let the OS decide what to call on runtime):
class Statement
{
virtual void exec() = 0;
};
class PrintStmt : public Statement
{
void exec()
{
std::cout << expression->eval();
};
class AssignStmt : public Statement
{
void exec()
{
vm->bind_var(name, expression->eval())
};
Any ideas how I can rework this so it can be compiled by a pure C compiler?
I know this is general question and there is no single answer, but how would you do this?
Note: I already downloaded the python code as a reference, but it will take time until I figure out how it is working.
Statement would be a struct. In addition to its data members, you will need a function pointer e.g.
struct Statement
{
void(*exec)(Statement* this); // Function pointer
// Other members
};
You would then have different implementations of the functions per statement type and a function for manufacturing objects of the right type e.g.
static void printExec(struct Statement* this)
{
printf("%s", this->whatever);
}
struct Statement* createPrintStatement()
{
struct Statement* statement = calloc(1, sizeof(struct Statement));
statement->exec = printExec;
return statement;
}
And you would invoke it like this:
statement->exec(statement);
The this pointer gives you access to the data members of the particular struct i.e. the instance whose exec method you invoked.
If you have lots of functions, consider using a vtable.
struct VTable
{
void(*exec)(Statement* this); // Function pointer
const char* (*stringValue)(Statement* this); // Function pointer
};
struct Statement
{
struct VTable* vtable;
// Other members
};
You build each a vtable for each kind of object only once
struct VTable printVTable =
{
printExec,
printStringValue
};
You create new objects thus:
struct Statement* createPrintStatement()
{
struct Statement* statement = calloc(1, sizeof(struct Statement));
statement->vtable = &printVTable;
return statement;
}
and invoke the methods thus
statement->vtable->exec(statement);
The vtable method is more or less what C++ does behind the scenes.
The most straightforward way to convert this to C would probably be to use function pointers.
As #DrewNorman said, you will need to understand how vtables work, class layouts etc, and reimplement it (at least partially) in C. The example code below is very limited but gives you a hint of what to expect.
struct Statement {
void (*exec)(struct Statement* s);
};
struct PrintStmt {
struct Statement statement;
char* what;
};
void print_function(struct Statement* s) {
struct PrintStmt* p = (struct PrintStmt*)s;
printf(p->what);
}
// ...
struct PrintStmt p;
p.statement.exec = &print_function;
p.what = "Hello world";
p.statement.exec(p);
There are numerous C projects that use this kind of technique, GObject comes to my mind but it's far from the only one.
(Note: I'm used to C++ not really to C so this may not even be valid C but you get the idea anyway)

Polymorphism determination issue

I have a problem I am working on. I have a number classes which inherit each other in this pattern:
#include <stdio.h>
#include <stdlib.h>
#include <list>
class TimeObject
{
public:
virtual void Tick()=0;
std::list<TimeObject*> ticks;
};
class MapObject : public TimeObject
{
public:
MapObject()
{
ticks.push_front(this);
printf("Create MapObject %p\n", this);
}
void Tick() { printf("mapobject tick\n"); }
};
class ControlObject : public MapObject
{
public:
ControlObject()
{
ticks.push_front(this);
printf("Create ControlObject %p\n", this);
}
void Tick() { printf("controlobject tick\n"); }
};
int main()
{
ControlObject test;
std::list<TimeObject*>::iterator it = test.ticks.begin();
for(; it != test.ticks.end(); it++)
{
TimeObject *trigger = *it;
trigger->Tick();
}
return 0;
}
The list in the example stores any TimeObject derived class. My problem is that when storing MapObject pointers in the list that are also ControlObjects dispatch always picks the ControlObject function.
Is it possible to trigger the MapObject function with a ControlObject pointer using polymorphism? If it isn't possible/pratical, what would be a good alternative?
You should always store pointer to the Base class A* in the list(std::list< A*>).
The pointer should be correctly made to point either a object of type Bor C before you add the pointer to the container.
Once you do that, dynamic dispatch will take care of calling the correct function for you depending on the actual object type. You don't need to do anything.
I don't know why you want to have any design which is otherwise, If you have any good reasons to do so please let know of them.
Why it always calls ControlObject::tick() in your code?
When you call:
ticks.push_front(this);
in ControlObject::ControlObject() you basically end up overwriting the first pointer you added to the list, The type of the first pushed pointer is not MapObject * anymore it is ControlObject * because you changed the pointer behind its back.You did not transfer ownership of the pointer to the list but you both had shared ownership and you modified the object in your list through the constructor call in derived class. This leaves you with two ControlObject * objects in the list which dynamic dispatch correctly determines and calls the correct method.
There is nothing wrong in what dynamic dispatch does, it is the correct behavior.
If you want to call MapObject::Tick(); then you will explicitly have to tell the compiler to do so, dynamic dispatch works on the actual type of object and it is working correctly.
void controlobject::Tick()
{
printf("controlobject tick\n");
MapObject::Tick();
}
Replicating from the comments:
I am afraid this is a bad design.The code works as it should,it works as defined by the C++ standard.The problem lies in the design.And unless you provide the details of what you are trying to achieve in a broader sense it is difficult and rather pointless to speculate on a new design.
Using a cast on the variable of type C to the type B should do the trick.
C c;
B b;
c.Function();
((B)c).Function();
A * l[] = {&c,&b,&c};
l[0]->Function();
l[1]->Function();
l[2]->Function();
B test = *(B*)l[0];
test.Function();
In your current example you should be able to call both virtual members (or just the one depending on the underlying type) by calling MapObject::Tick() inside ControlObject::Tick():
class ControlObject : public MapObject
{
public:
ControlObject()
{
ticks.push_front(this);
printf("Create ControlObject %p\n", this);
}
void Tick() { printf("controlobject tick\n"); MapObject::Tick(); }
};
The explicit function call notation is required.