Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

pointer pointing to a class object created from template for later use?

Description:
I was trying to create a class object based on the user input. I tried to store its reference with a pointer and use it at a later stage. A similar idea with the variable type late in Dart language. Is it possible to have this operation in CPP and if so, what kind of variable type should I use?

Code:

#include <iostream>
#include <vector>
using namespace std;

template <typename T>
class foo {
    public:
        T item;
        foo(){}
};

class bar_1 {
    public:
        int value = 99;
        void randomise();
};

class bar_2{
    public:
        string value = "init";
        void randomise();
};

int main()
{
    int i;
    cin >> i;
    void* ptr;
    if (i > 0) {
        ptr = new foo<bar_1>;
    }
    else {
        ptr = new foo<bar_2>;
    }

    // maybe run the function to randomise 'value'
    // ptr->item.randomise();
    cout << ptr->item.value;
    return 0;
}

Error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

cout << ptr->item.value;
|          ^~
error: ‘void*’ is not a pointer-to-object type

>Solution :

Definitely not in the way dynamic languages like JS and (AFAIK) Dart allow.

C++ is statically typed, so by the time you write cout << ptr->item.value in a (non-template) function, the types of item and value must be known. No way conflating unrelated types like int and string at runtime.

However, you may be able to use inheritance to achieve desired effect. A pointer to an object may always be converted to a pointer to its (accessible, i.e. public in most cases) base, and accessed like that base—but the object will retain its actual type, and all virtual methods of base will act on that type, and can be overriden:

class foo {
public:
    virtual ~foo() = default; // optional but highly recommended
    virtual randomize() {
        // the default implementation
    }
    // or: virtual randomize() = 0; // if you want ALL subclasses to override it
};

class bar_1: public foo {
public:
    int value = 99;
    void randomize() override {
        // the bar_1-specific implementation
    }
};

class bar_2: public foo {
public:
    std::string value = "something";
    void randomize() override {
        // the bar_2-specific implementation
    }
};

...

foo *obj = new bar_1(); // create an object of type bar_1, but treat it as foo
obj->randomize(); // will call bar_1::randomize as obj points to an object of type bar_1
// obj->value = 42; // won’t work: value is not a member of foo
delete obj;

obj = new bar_2(); // now, create an object of type bar_2, but treat it as foo again
obj->randomize(); // will call bar_2::randomize as obj now points to an object of type bar_2
delete obj;

Or with smart pointers (highly recommended):

std::unique_ptr<foo> obj = std::make_unique<bar_1>()
// std::unique_ptr<foo> obj{new bar_1()}; // if you can’t afford C++17
obj->randomize();

obj = std::make_unique<bar_2>();
// obj.reset(new bar_2()); // if you can’t afford C++17
obj->randomize();
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading