2 replaced http://stackoverflow.com/ with https://stackoverflow.com/
source | link

Here's a minimal task setup, you'll need to add your task state (enabled/disabled, next start time, etc.) in there, and adapt your scheduler to use this: (see How can I store a lambda expression as a field of a class in C++11?How can I store a lambda expression as a field of a class in C++11?)

  • Make sure you understand the difference between a class declaration and definition, and what you can do with an incomplete type (on that has been declared but not defined). See for example Does not name a type error in C++Does not name a type error in C++, and for more info When can I use a forward declaration?When can I use a forward declaration?.
  • Don't try and bypass a type error with a void*. Understand your problem and fix it. Types are central to C++, and void* is as close as to a "non-type" as possible. The compiler can't help you with it, can't warn you about type errors when you use that.
  • Be more careful with your syntax. If t is a pointer t.foo() is wrong. This isn't Java. Classes and struct definitions must end with a ; (struct foo {};). Forgetting that semicolon will lead you to very bizarre compiler errors.
  • Don't use new, this isn't Java. Use std::shared_ptr and/or std::unique_ptr with their std::make_shared/std::make_unique helpers. This will same you a lot of memory management issues, and exception-safety gotchas.
  • More reading on lambdas: What is a lambda expression in C++11?What is a lambda expression in C++11?, Lambda Expressions

Here's a minimal task setup, you'll need to add your task state (enabled/disabled, next start time, etc.) in there, and adapt your scheduler to use this: (see How can I store a lambda expression as a field of a class in C++11?)

  • Make sure you understand the difference between a class declaration and definition, and what you can do with an incomplete type (on that has been declared but not defined). See for example Does not name a type error in C++, and for more info When can I use a forward declaration?.
  • Don't try and bypass a type error with a void*. Understand your problem and fix it. Types are central to C++, and void* is as close as to a "non-type" as possible. The compiler can't help you with it, can't warn you about type errors when you use that.
  • Be more careful with your syntax. If t is a pointer t.foo() is wrong. This isn't Java. Classes and struct definitions must end with a ; (struct foo {};). Forgetting that semicolon will lead you to very bizarre compiler errors.
  • Don't use new, this isn't Java. Use std::shared_ptr and/or std::unique_ptr with their std::make_shared/std::make_unique helpers. This will same you a lot of memory management issues, and exception-safety gotchas.
  • More reading on lambdas: What is a lambda expression in C++11?, Lambda Expressions

Here's a minimal task setup, you'll need to add your task state (enabled/disabled, next start time, etc.) in there, and adapt your scheduler to use this: (see How can I store a lambda expression as a field of a class in C++11?)

  • Make sure you understand the difference between a class declaration and definition, and what you can do with an incomplete type (on that has been declared but not defined). See for example Does not name a type error in C++, and for more info When can I use a forward declaration?.
  • Don't try and bypass a type error with a void*. Understand your problem and fix it. Types are central to C++, and void* is as close as to a "non-type" as possible. The compiler can't help you with it, can't warn you about type errors when you use that.
  • Be more careful with your syntax. If t is a pointer t.foo() is wrong. This isn't Java. Classes and struct definitions must end with a ; (struct foo {};). Forgetting that semicolon will lead you to very bizarre compiler errors.
  • Don't use new, this isn't Java. Use std::shared_ptr and/or std::unique_ptr with their std::make_shared/std::make_unique helpers. This will same you a lot of memory management issues, and exception-safety gotchas.
  • More reading on lambdas: What is a lambda expression in C++11?, Lambda Expressions
1
source | link

Your main problem appears to be that your design makes your classes know too much about each other, which will give you headaches with cyclic dependencies and inextricable ownership issues – especially since you're apparently using raw pointers a lot.

Your Task abstraction shouldn't know anything about Meter, or if it does, it should know about an abstract base class for your meters, and rely exclusively on that. And Meter should be completely oblivious of the Task system. This will enable you to have a task and scheduler abstraction that are either completely generic, or only depend on a well-defined interface.

You state in comments that going with an abstract base class and virtual methods would be too heavy, so a "generic" task abstraction should be the way to go. Tools to build that in C++ would either be templates, or in this case using a std::function to hide the actual type (and "nature") of the task to be run.

Here's a minimal task setup, you'll need to add your task state (enabled/disabled, next start time, etc.) in there, and adapt your scheduler to use this: (see How can I store a lambda expression as a field of a class in C++11?)

#include <functional>

struct Task
{
    Task(std::function<bool()> f): func(f) {}
    bool execute()
    {
        return func();
    }
private:
    std::function<bool()> func;
};

You can use this utility to schedule ordinary functions, or lambdas – std::function takes care of hiding the actual type of the callable it handles for you.

Example usage:

#include <iostream>
#include <vector>

#include "task.h"

bool foo()
{
    std::cout << "Fooing" << std::endl;
    return true;
}

struct Meter
{
    Meter(std::string n): name(n) {}
    bool process_events()
    {
        std::cout << "Processing " << name << std::endl;
        return true;
    }
private:
    std::string name;
};

int main()
{
    Meter m { "CPU" };
    std::vector<Task> tasks;
    tasks.emplace_back(foo);
    tasks.emplace_back([&m](){return m.process_events();});

    for (auto& task: tasks)
        task.execute();
}

Now this looks wrong:

class XOSView : public XWin, public Scheduler { ... };

A window isn't a scheduler, a scheduler isn't a window, and a game isn't either of those either. That sort of construct is will give you more headaches going further than you already have. Use composition. Your game should have a UI, and have a scheduler, and a bunch of other stuff. It shouldn't be a UI and a scheduler at the same time.

_xos->sched_insert(t);

Transform that to use a member scheduler object:

_xos->sched().insert(t);

Then figure out whether your meters need to know about the game controller or the UI. If they need both (what I understand from your comment), pass a reference to both during construction until the time you can make a better interface between those.

Multiple inheritance is very easy to get wrong, even more so than plain inheritance (which is difficult enough already). Avoid it unless you know better.


Random advice:

  • Make sure you understand the difference between a class declaration and definition, and what you can do with an incomplete type (on that has been declared but not defined). See for example Does not name a type error in C++, and for more info When can I use a forward declaration?.
  • Don't try and bypass a type error with a void*. Understand your problem and fix it. Types are central to C++, and void* is as close as to a "non-type" as possible. The compiler can't help you with it, can't warn you about type errors when you use that.
  • Be more careful with your syntax. If t is a pointer t.foo() is wrong. This isn't Java. Classes and struct definitions must end with a ; (struct foo {};). Forgetting that semicolon will lead you to very bizarre compiler errors.
  • Don't use new, this isn't Java. Use std::shared_ptr and/or std::unique_ptr with their std::make_shared/std::make_unique helpers. This will same you a lot of memory management issues, and exception-safety gotchas.
  • More reading on lambdas: What is a lambda expression in C++11?, Lambda Expressions