#Help with abstract classes

52 messages · Page 1 of 1 (latest)

ivory socket
#

Hey, so I'm working on a simple app where I can enable some functions by clicking buttons.
I'm trying to make an abstract class called Module and then other classes that would deriver from it like ShowTime ShowDay ShowWeather

burnt cedarBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

ivory socket
#

module.hpp

#include <string>

class Module
{
private:
    std::string Name;
public:
    

    Module(std::string name)
    {
        Name = name;
    }

    virtual void Update() = 0;

    std::string GetName()
    {
        return Name;
    }
};
#

then I have other modules:
showTime.cpp

#include "../module.hpp"

class ShowTime: public Module
{
    public:
        ShowTime(std::string name) : Module(name){}

        void Update()
        {
                    //showTime
        }
};
#

I have a moduleManager.hpp

#include "module.hpp"
#include <list>

namespace ModuleManager
{
    static std::list<Module> Modules;

    void Init();
    void Update();
}
#

and a moduleManager.cpp

namespace ModuleManager
{
    void Init()
    {
        ShowTime showTime(std::string("ShowTime"));
        Modules.push_back(showTime);
    }

    void Update()
    {
        for (const Module& m : Modules)
        {
            std::cout << m.GetName() << std::endl;
        }
    }
}
#

I have experience with OOP in c# but c++ is black magic for me

dusty oasis
#

std::list<Module> can only store Modules, not things derived from Module such as ShowTime.

ivory socket
#

i see

#

thats a shame

dusty oasis
#

You probably want to switch to std::list<std::unique_ptr<Module>> to get around that problem.

ivory socket
#

okay but now push_back doesnt work

#

i guess i need to create a pointer to the object?

#

and then add it to the list

#

nope, im wrong

dusty oasis
#

Modules.push_back(std::make_unique<ShowTime>("ShowTime")); should work.

ivory socket
#

alright

#

seems to work

#

what about the for loop?

dusty oasis
#

Module is now an std::unique_ptr<Module>, so you have to do m->GetName() instead of m.GetName().

ivory socket
#

alright, thanks

#

hmm im still getting a bunch of errors when trying to build

#

'Module': 'class' type redefinition (compiling source file Modules\moduleManager.cpp)

#

'Module': base class undefined (compiling source file Modules\moduleManager.cpp)

#include "../module.hpp"

class ShowTime: public Module
{
    public:
        ShowTime(std::string name) : Module(name){}

        void Update()
        {

        }
};
dusty oasis
#

Did you forget header guards in Module.hpp?

ivory socket
#

header guards?

#

okay i deleted #include "module.hpp" from moduleManager.cpp and i got rid of some errors

#

im still getting the Module: class type redefinition tho

dusty oasis
#

Hmm, no, moduleManager.cpp will most definitely need module.hpp.

ivory socket
#

why? moduleManager.cpp includes moduleManager.hpp which includes module.hpp

#

it doesnt work like this?

dusty oasis
#

It does, but ... relying on implicit includes it somewhat frowned upon.

#

A classic header guard looks like

#ifndef MODULE_H
#define MODULE_H

//content

#endif
#

But all compilers support just writing #pragma once instead which is non-standard.

ivory socket
#

yep

#

adding it solved everything

#

could you explain why i need to do this stuff?

dusty oasis
#

Nice

#

Well, C++ has a rule that you can only have 1 definition for things.

#

You can't do

struct S {};
struct S {};
#

That means you defined S twice.

#

#include "header" just means "open the file and copy/paste its contents here".

#

So if you do ```cpp
#include "header"
#include "header"

then you get everything twice.
#

The header guard prevents that by expanding to

#ifndef HEADER
#define HEADER
//content
#endif

#ifndef HEADER
#define HEADER
//content
#endif
#

The second //content is ifdefed away.

ivory socket
#

okay so I guess putting #pragma once most of the time is a good approach?

dusty oasis
#

It's a matter of ideology. Decide if you care more for convenience or standard compliance.

#

#pragma once is widely accepted though, so in this case it's fine to lean towards convenience.

ivory socket
#

convenience, its just a pocket project

#

anyway, thanks for help

burnt cedarBOT
#

@ivory socket Has your question been resolved? If so, type !solved :)

ivory socket
#

!solved