简体   繁体   中英

How to put unknown child classes of a base class in one data structure and call an overridden base class function in C++

I have a "chain" class, meaning a class that manages a sequence of objects with a common base class. This chain class should execute the member function processSample(a, b) for any child class (of baseClass ) I add.

I want to be able to code more child classes (with a processSample(a, b) function) later on, and add them to the chain without having to edit the chain class. I could use a template in the add function but this doesn't solve the problem that there is no data structure for different datatypes (of different sizes) right?

Functions of the children called in the Chain class should all be overridden virtuals from the base class.

class baseClass
{
public:

    virtual float processSample(int a, float b)
    {

    }
};


class Chain
{
    const int maxChilds = 20;
    ?sometype? allChilds[maxChilds];

public:
    float processSample(int c, float d)
    {
        for (int i = 0; i < maxChilds; i++)
        {
            input = allChilds[i].processSample(a, b);
        }

        return input;
    }

    void addChild(?sometype? newChild)
    {
       allChilds.push_back(newChild)
    }
}

You would want to use pointers or references, to avoid initialization or copy operations as part of creating the class.

For example

class Chain
{
    const int maxChilds = 20;
    baseClass allChilds[maxChilds];

Will create, and initialize an array of 20 baseClass instances. Whereas this:

class Chain
{
    const int maxChilds = 20;
    baseClass* allChilds[maxChilds];

Will create an array of pointers to baseClass, which can also point to instances of any child classes. Do consider which class will be responsible for allocation and de-allocation of the memory for these instances (this can either be within this class, or the caller / user of this class - which one is ideal will depend on the rest of your design). You could also consider using a smart pointer instead and let that manage the memory for you: https://en.cppreference.com/book/intro/smart_pointers

Similarly:

void addChild(baseClass newChild)

Will use pass-by-value to pass in a copy of newChild (using the copy constructor of baseClass), any instances of child classes will either fail or be converted to an instance of baseClass. Whereas if you instead go with:

void addChild(baseClass& newChild)

It will use pass-by-reference instead, and the function will receive a reference to the original object.

The nice effect of virtual is, that you "call a function of the base class", but the function of the derived class will be executed.

So ?sometype? allChilds[maxChilds]; ?sometype? allChilds[maxChilds]; is baseClass allChilds[maxChilds]; . The chain should be the holder of the objects, so addChild(...) should not accept an instance of the child-class. It should create the instance and use (if necessary) std::move to add it to the array.

Remark: It will be easier for you using

std::vector<baseClass>allChilds;
allChilds.reserve(maxChilds); //reserves the memory but you can still use push back

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM