0

I am trying to implement a spawning system for a project in which I have a container class (in that case it is essentially the world) which can hold any world-object, of which there are several derived classes.

Because the container class has information relevant to the instantiation of a derived class (that an external class calling the spawn method has no need for) I figured it would make sense to use a templated member function where the type which the function is being called for is specified as such

containerClass.functionName<type>(/*no arguments specifying the type*/);

without templating the container class (because the class contains multiple types of objects)

This may be my misunderstanding, but can not the information of which type to pass be taken from the values between the brackets (or whatever these <> are commonly known as)?

The following (simplified) code was my implementation of such a task given my understanding of templates:

#include <vector>
#include <iostream>

class baseClass {
    public:
        virtual const char* getName() { return "baseClass"; }
};

class derivedA : public baseClass {
    public:
        const char* getName() { return "derivedA"; }
};

class derivedB : public baseClass {
    public:
        const char* getName() { return "derivedB"; }
};

class container {
    public:
        container() {}
        ~container() {
            for (int i = 0; i < contained.size(); ++i) {
                delete contained[i];
            }
        }
        template <typename type> void spawn() {
            contained.push_back(new type(/*in my case the container  has data with which to initialize the class*/));
        }
        void printNames() {
            for (int i = 0; i < contained.size(); ++i)
                std::cout << contained[i]->getName() << std::endl;
        }

    private:
        std::vector<baseClass*> contained;
};


int main() {
    container c;

    c.spawn<derivedA>();
    c.spawn<derivedB>();
    c.spawn<derivedA>();

    c.printNames();

    return 0;
}

This works as expected (given a modification from the original question) producing

derivedA
derivedB
derivedA

Although I have yet to get this to work in my actual project (which gives me a linker error saying the particular template method does not exist) I am wondering if this is valid C++ and/or a good practice. Are there more advisable ways of implementing this?

I would much appreciate someone explaining how best to implement such a function, preferably without passing unused instantiations.

On a less professional note (which I am sure some user will edit out...) I apologize for the length of this question. For the same reason that I imagine this may be a duplicate post, I do not know the terminology with which to best explain my situation. If you somehow bore through that all, I thank you for your patience!

  • 1
    You'll want those `virtual` functions to return `const char*` rather than `char*`. – François Andrieux Apr 27 '18 at 14:45
  • 2
    `baseClass` is always an instance of `baseClass`. For polymorphism you need a pointer or reference. Try `std::vector>`. – François Andrieux Apr 27 '18 at 14:46
  • @FrançoisAndrieux Thank You! That seems to have solved my problem, although I am still hoping for some confirmation of if this general system works. Should I post an answer with the corrected version or scrap the question? – Christian Fluharty Apr 27 '18 at 14:54
  • You're allowed to answer your own question on Stack Overflow. Though to post an answer, you should be sure it's correct. It's not correct to post them asking for confirmation for your solution. Perhaps you could append your fixed version to the question. – François Andrieux Apr 27 '18 at 15:04
  • Note that changing the question such that the original meaning is lost is discouraged as it eliminates context information for future readers. – François Andrieux Apr 27 '18 at 15:05
  • Modern c++ should [avoid using new](https://stackoverflow.com/questions/7620385/why-is-it-a-bad-idea-to-use-new) in most cases. Prefer smart pointers like `std::unique_ptr` instead of raw owning pointers and `std::make_unique` instead of `new`. – François Andrieux Apr 27 '18 at 15:06

0 Answers0