1

I am trying to convert a project from c# to c++ and have come across a piece of functionality I am not sure on how to implement in c++.

I have a list (or vector) of objects, all casted to their parent type. In c# I can call a function from an object in this list without knowing the child and the appropriate child function will be called, however I am not sure how to make this certain functionality work in c++.

Code snippet from C#:

        public void AddComponent(IComponent component)
    {
        Debug.Assert(component != null, "Component must not be null");

        componentList.Add(component);
        mask |= component.ComponentMask;
    }

Retrieves the ComponentMask enum value from the Component and performs bitwise operation correctly.

Code snippet from C++:

void oEntity::AddComponent(IComponent &componentIn)
{
    componentList.push_back(componentIn);
    mask |= componentIn.ComponentMask();
}

This returns the error "IComponent cannot instantiate abstract class", if I remove the brackets from the method the operator overload no longer works and throws the error "binary '|=': no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)"

The mask value is an enum that contains bit shifted ints used as a flag to identify the component type. Operator has also been overloaded appropriately to work with the enum type.

Naglfar705
  • 69
  • 2
  • 5
    *I have a list (or vector) of objects, all casted to their parent type*. That's a problem in C++. Your code suffers from [object slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing). Use a `std::vector>` instead. – R Sahu Jun 06 '18 at 15:27
  • 4
    [Get a couple of good C++ books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) and start reading. Of special interest for this problem, read about *pointers*, *polymophism* and *virtual functions*. – Some programmer dude Jun 06 '18 at 15:27
  • 3
    In C++, runtime polymorphism is based on pointers. You need vector/list of pointers of type `IComponent*` (or unique/shared pointers) and then store pointers to instances of inherited classes. Via these pointers, you can then call virtual methods such as `ComponentMask`. – Daniel Langr Jun 06 '18 at 15:30
  • Correction to my previous comment. Use a `std::vector>` instead. – R Sahu Jun 06 '18 at 15:46
  • 2
    Thank you for your speedy responses, they were very helpful and helped me fix my problem and also made me learn something in the process. – Naglfar705 Jun 06 '18 at 16:36

1 Answers1

0

The OP has already figured it out, so this is for anyone else coming across this question.

In C++, you can declare virtual methods (you can also declare pure virtual methods, but that's a bit more complex). These methods can be overwritten by child classes, but must be implemented them selves as well, or you'll get some cryptic errors.

If you want them to do nothing by default, the easiest solution is to just define them with an empty body. Here's a simple example:

class ParentClass
{
    int x, y;
    virtual void handleNewPos(int newX, int newY){}

public:
    ParentClass(int x, int y)
    {
        resetPos(x, y);
    }

    void resetPos(int newX, int newY)
    {
        handleNewPos(newX, newY);
        x = newX;
        y = newY;
    }
}

class ChildClass: public ParentClass
{
    // marked 'override' because it's replacing a previous virtual method that had the same
    // return type / params. Not required, but if you're using C++11 or greater, than it's
    // preferred 
    virtual void handleNewPos(int newX, int newY) override
    {
        // Every time the resetPos method is called, it prints out it's new position.
        std::cout << "New Position: " << newX << ", " << newY << std::endl;
    }      

public:
    ChildClass(int x, int y): ParentClass(x, y) {}                                          
}
J. Doe
  • 305
  • 1
  • 11