c++objectinitializationnew-operatorderived-class

Is there a way to make class name as a variable? ... parent_class *p_derived = new classnamehere();


I'm trying to follow DRY and I want to put initialization of a new class in function but there is one problem. My class is a parent class and I'm initializating new derived class in this function.

Samples:

Class declaration:

#include <iostream>
class parent
{
private:
    int m_number;
public:
    parent() {}
    virtual void say_hello() { std::cout << "Hello. This is parent class!" << std::endl; }
    ~parent() {}
};

class derived1 : public parent
{
public:
    derived1(){}
    void say_hello() override { std::cout << "Hello. This is first derived class!" << std::endl; }
    ~derived1(){}
};
class derived2 : public parent
{
public:
    derived2() {}
    void say_hello() override { std::cout << "Hello. This is second derived class!" << std::endl; }
    ~derived2() {}
};

Enum states:

enum OutputMethod
{
    STATE_NONE,
    STATE_CLASS,
    STATE_EXIT
};

Actions for testing:

#include <Windows.h>
#define VK_L_C 0x43
#define VK_L_N 0x4E
void action(OutputMethod &state)
{
    if (GetKeyState(VK_L_C) < 0)
    {
        state = STATE_CLASS;
    }
    else if (GetKeyState(VK_L_N) < 0)
    {
        state = STATE_NONE;
    }
    else if (GetKeyState(VK_ESCAPE) < 0)
    {
        state = STATE_EXIT;
    }
}

Main:

#include <iostream>
#include <string>
int main(void)
{
    derived1 *p_derived = nullptr;
    OutputMethod out_method;

    out_method = STATE_NONE;

    while (out_method != STATE_EXIT)
    {
        // Actions (C-class, N-none, ESC-endloop)
        action(out_method);

        //--------BEGINING of desired function----------
        if (out_method == STATE_NONE)
        {
            std::cout << "Hello from main!" << std::endl;
        }
        else if (out_method == STATE_CLASS)
        {
            if (p_derived == nullptr)
            {
                // There is the problem (derived1 name should be variable)
                p_derived = new derived1();
            }

            p_derived->say_hello();
        }

        if (out_method == STATE_NONE)
        {
            if (p_derived != nullptr)
            {
                delete p_derived;
                p_derived = nullptr;
            }
        }
        //-------------END of desired function----------
    }

    if (p_derived != nullptr)
    {
        delete p_derived;
        p_derived = nullptr;
    }

    std::string exit = "";
    std::getline(std::cin, exit);

    return 0;
}

I'm not sure how to do it.

I've tried to make a function to deal with this problem:

void output_state(parent *p_variable, parent* p_new, OutputMethod state_0, OutputMethod state_1, OutputMethod &state)
{
    if (state == state_0)
    {
        std::cout << "Hello from main!" << std::endl;
    }
    else if (state == state_1)
    {
        if (p_variable == nullptr)
        {
            // There is the problem (p_new is not a name var but a new object init)
            p_variable = p_new;
        }

        p_variable->say_hello();
    }

    if (state == state_0)
    {
        if (p_variable != nullptr)
        {
            delete p_variable;
            p_variable = nullptr;
        }
    }
}

Calling in main:

...
derived1 *p_derived = nullptr;
OutputMethod out_method;
out_method = STATE_NONE;

while (out_method != STATE_EXIT)
    {
        // Actions (C-class, N-none, ESC-endloop)
        action(out_method);
        output_state(p_derived, new derived1(), STATE_NONE, STATE_CLASS, out_method);
    }
...

But the problem is that I don't want to init a new object everytime I call the function and I'm not sure how to make the check to be able to call the function but at the same time preventing initializing a new object.

Am I missing something?

P.S: Sorry for the long code but when I post a short code, I get replies that people cannot read my mind but if I post all the necessary parts, I get replies that the code is too long and unreadable.


Solution

  • It seems that you want your function to produce an object of given type. A template can do that:

    template<class ObjType>
    OutputMethod  output_state( parent *p_variable, OutputMethod state_0, OutputMethod state_1, OutputMethod state ) {
        if ( state == state_0 ) {
            std::cout << "Hello from main!" << std::endl;
        }
        else if ( state == state_1 ) {
            if ( ! p_variable ) {
                p_variable = new ObjType{};
            }
            p_variable->say_hello();
        }
        if ( state == state_0 ) {
            if ( p_variable ) {
                delete p_variable;
                p_variable = nullptr;
            }
        }
        return  state;
    }
    

    And in main:

        while ( out_method != STATE_EXIT ) {
            // Actions (C-class, N-none, ESC-endloop)
            action(out_method);
            out_method = output_state<Derived1>( p_derived, STATE_NONE, STATE_CLASS, out_method );
        }
    

    Notice that I left p_variable as raw pointer, but it is largely safer to use std::unique_ptr<>.