Godot Engine C ++ and GDnative. How to use abstract classes?. "Data type abstract problem"

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ariel

Does Godot Engine with C ++ support abstract classes?

I made an abstract class in C ++.

The “.h”

// Godot engine C++ Gdnative Estructura de un archivo
#ifndef TESTABTRACTCLASS_H
#define TESTABTRACTCLASS_H

#pragma once


#include <Godot.hpp>
#include <Node.hpp>


namespace godot {
    //Testing an abstract class with C ++ for use with GDnative
	class TestAbstracClass : public Node {

        private:
            GODOT_CLASS(TestAbstracClass, Node)  

        public:
            TestAbstracClass();
            ~TestAbstracClass();
            void _init();
            void _ready();
            static void _register_methods();

        protected:
            virtual void Walk() = 0; //virtual
            virtual void Run() = 0; //virtual
            virtual void Attack() = 0; //virtual
            virtual void Jump() = 0; //virtual
	};
}

#endif	

The “.cpp”

#include "TestAbstracClass.h"

using namespace godot;

TestAbstracClass::TestAbstracClass() {}

TestAbstracClass::~TestAbstracClass() {}

void TestAbstracClass::_init() {}

void TestAbstracClass::_ready() {}

void TestAbstracClass::_register_methods() {}

As you can see, the class is abstract because it has 4 pure virtual methods that are going to be defined in the classes that inherit from it.

---------------------------------------------------

However I see that it does not compile, it seems that it does not support the abstract data type, that is, this error appears naming all the abstract methods .

D: \ GODOT ENGINE C ++ PROJECTS \ GodotMatematicalGameCPP \ godot-cpp \ include \ core \ Godot.hpp (153): note: 'void godot :: TestAbstracClass :: Walk (void)': it is abstract

D: \ GODOT ENGINE C ++ PROJECTS \ GodotMatematicalGameCPP \ godot-cpp \ include \ core \ Godot.hpp (171): note: See the reference to creating an instance of the template function "void * godot :: _ godot_class_instance_func <T> (godot_object *, void *) "which is being compiled
         with
         [
             T = godot :: TestAbstracClass
         ]

---------------------------------------------------

Does GDnative with c ++ support abstract classes?

What can you do or what do you recommend if you can’t stand them?

Any example project?

If the methods are virtual it seems that it does not work either.

protected:
            virtual void Walk(); //virtual
            virtual void Run(); //virtual
            virtual void Attack(); //virtual
            virtual void Jump(); //virtual
	};

------------------------------------------------------------------

TestAbstracClass.obj: error LNK2001: external symbol "protected: virtual void __cdecl godot :: TestAbstracClass :: Walk (void)" (? Walk @ TestAbstracClass @ godot @@ MEAAXXZ) unsolved

TestAbstracClass.obj: error LNK2001: external symbol "protected: virtual void __cdecl godot :: TestAbstracClass :: Run (void)" (? Run @ TestAbstracClass @ godot @@ MEAAXXZ) unsolved

TestAbstracClass.obj: error LNK2001: external symbol "protected: virtual void __cdecl godot :: TestAbstracClass :: Attack (void)" (? Attack @ TestAbstracClass @ godot @@ MEAAXXZ) unresolved

TestAbstracClass.obj: error LNK2001: external symbol "protected: virtual void __cdecl godot :: TestAbstracClass :: Jump (void)" (? Jump @ TestAbstracClass @ godot @@ MEAAXXZ) unsolved

Godot_proyect \ GDnative_Plugin_DLL \ win64 \ libgdexample.dll: fatal unresolved external error LNK1120: 4

scons: *** [Godot_proyect \ GDnative_Plugin_DLL \ win64 \ libgdexample.dll] Error 1120
scons: building terminated because of errors.

The terminal process "C: \ Windows \ System32 \ WindowsPowerShell \ v1.0 \ powershell.exe -Command scons platform = windows target = debug" terminated with exit code: 1.

ariel | 2021-09-04 12:58

:bust_in_silhouette: Reply From: sash-rc

Does GDnative with c ++ support abstract classes?

This is C++, not GDnative that doesn’t allow instantiating of abstract classes. Example:

class Abstract
{
  virtual void method() = 0;
};
class Concrete : public Abstract
{
  virtual void method() override {};
};

Abstract a; // ---- error: you can't call Abstract() constructor
Abstract* b = new Concrete(); // but you can have such variable for compatible (inherited) types

Sure, but I’m not instantiating the class, I’m just defining it, the compiler throws the error as soon as you mark a method as pure virtual and converts the class into abstract. One way I found after doing several tests, is to use the class with virtual methods, but without being pure virtual, so the class is never abstract … create a long comment here Below. Thanks for the clarification, I did not know that a pointer could be used to refer to an abstract class, layers that is the solution, but no idea how it works with the Godot Engine framework with GDnative and prevent the program from crashing when using abstract classes …

ariel | 2021-09-06 15:17

It says you can’t call the constructor? … Take the constructor method out of the abstract class and the same thing happens … If I define a method as pure virtual, the compiler throws an error

 // virtual for overwriting
            virtual void Walk() = 0;

D: \ GODOT ENGINE C ++ PROJECTS \ GodotMatematicalGameCPP \ godot-cpp \ include \ core \ Godot.hpp (171): note: See the reference to creating an instance of the function
template "void * godot :: _ godot_class_instance_func <T> (godot_object *, void *)" being compiled
         with
         [
             T = godot :: AbstractCharacter
         ]

ariel | 2021-09-06 15:23

Happen to stumble across this(for anyone in the future), as you may have found out you can’t create a abstract class with Gdnative, because I am pretty sure they are already declared as an abstract class through how you declare a class as a Godot Class. From you example above, the GODOT_CLASS(Class,GodotType) does some template and or abstract magic to initialize everything.

class PersonajeAbstracto : public KinematicBody {

        private:
            GODOT_CLASS(PersonajeAbstracto, KinematicBody)  //This guy 

Sadly this how it all works currently, unless this gets reworked it is what it is.

r.bailey | 2021-10-30 00:06

:bust_in_silhouette: Reply From: ariel

After doing several tests I verified that it is not possible to use abstract classes in a simple way, however it is possible to use virtual methods and overwriting them in the child classes. Although the classes are not abstract, at least the methods and methods can be overwritten. do something similar.

I declare the virtual method

I implement the virtual method

I override the virtual method

I implement virtual method on writing and also call the parent method, if necessary.

THIS WOULD LOOK LIKE IN VScode

I leave the example the father and daughter class

parent class

.h

// Godot engine C++ Gdnative Estructura de un archivo
#ifndef PERSONAJEABSTRACTO_H
#define PERSONAJEABSTRACTO_H

#pragma once


#include <Godot.hpp>
#include <KinematicBody.hpp>


namespace godot {
    //Testing an abstract class with C ++ for use with GDnative, ojo funciona con clases abstractas simuladas
	class PersonajeAbstracto : public KinematicBody {

        private:
            GODOT_CLASS(PersonajeAbstracto, KinematicBody)  

        public:
            PersonajeAbstracto();
            ~PersonajeAbstracto();
        
            void _init();
            void _ready();
            static void _register_methods();

        protected:
            // virtual for overwriting
            virtual void Walk(); 
            // virtual for overwriting
            virtual void Run();
            // virtual for overwriting
            virtual void Attack();
            // virtual for overwriting
            virtual void Jump(); 
	};
}

#endif

.cpp

#include "PersonajeAbstracto.h"

using namespace godot;

PersonajeAbstracto::PersonajeAbstracto() {}

PersonajeAbstracto::~PersonajeAbstracto() {}

void PersonajeAbstracto::_init() {}

void PersonajeAbstracto::_ready() {}

void PersonajeAbstracto::Walk() { Godot::print("DESDE CLASE PADRE"); }

void PersonajeAbstracto::Run() {}

void PersonajeAbstracto::Attack() {}

void PersonajeAbstracto::Jump() {}


void PersonajeAbstracto::_register_methods() 
{
}

## Daughter class

## .h



    #ifndef MOMIA_H
    #define MOMIA_H
    
    #pragma once
    
    #include <Godot.hpp>
    #include "PersonajeAbstracto.h"
    #include "KinematicBody.hpp"
    
    
    namespace godot {
    	class Momia : public PersonajeAbstracto {
           
            private:
                GODOT_CLASS(Momia, PersonajeAbstracto)  
    
            public:
                
                Momia();
                
                ~Momia();
            
                static void _register_methods();
            
            
                //metodo inicial siempre hay que declararlo
                void _init();
    
                void _ready();
    
            private:
                // I override the function and call the parent method at the same time
                void Walk() override;
                void delay(int secs);
    	};
    }
    
    #endif



## .cpp



    #include "Momia.h"
    
    using namespace godot;
    
    Momia::Momia() 
    {
        
    }
    
    Momia::~Momia() 
    {
    }
    
    void Momia::_init() 
    {
        
    }
    
    void Momia::_ready() 
    {
        Walk();
    }
    
    void Momia::Walk() 
    {
        PersonajeAbstracto::Walk();// If you want you can call the parent method
        Godot::print("DESDE CLASE LA MOMIA");
    }
    
    
    
    void Momia::_register_methods() 
    {
        register_method("_ready",&Momia::_ready);
    }