В Java вы можете создать объект, одновременно предоставляя (или перегружая) абстрактные функции внутри объекта, таким образом:
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Whatever in here
}
};
Мне действительно нравится такой способ, и мне было интересно, есть ли в C ++ похожая конструкция.
По сути, мне нужен базовый класс с объявленной в нем парой PV-функций (среди прочего) и пользователь, чтобы создать экземпляр этого класса и в то же время предоставить тело PV-функций.
Я знаю, что могу создавать дочерние классы, но это кажется немного неуклюжим для того, что мне нужно, где каждый дочерний класс будет уникальным и будет использоваться только для создания одного экземпляра каждого.
Я думал о том, чтобы предоставлять lamdas конструктору и использовать их вместо реальных функций-членов, но это действительно кажется грязным и трудным для начинающего пользователя - не говоря уже о том, что он будет слишком жестким (я я также хотел бы иметь возможность переопределять некоторые не чистые виртуальные функции по желанию).
Так что дочерние классы - единственный путь, или есть какая-то менее известная конструкция в каком-то более новом стандарте C ++, о котором я не знаю, который мог бы делать то, что я хочу?
Чтобы немного расширить - идея в том, чтобы иметь такой класс:
class Thread {
// other stuff
public:
virtual void setup() = 0;
virtual void loop() = 0;
// other functions, some virtual but not pure
};
Thread threadOne {
void setup() {
// Init code for this thread
}
void loop() {
// Run code for this thread
}
};
Thread threadTwo {
void setup() {
// Init code for this thread
}
void loop() {
// Run code for this thread
}
};
Очевидно, что не тот синтаксис, но он дает вам представление о том, как я хотел бы использовать класс.
Он предназначен для работы во встроенной системе с упрощенной реализацией C ++ (это g ++, но без полной STL). Конечные пользователи - не самая лучшая группа, поэтому ее нужно понимать как можно проще.
Анонимные дочерние классы ближе всего к тому, что я хотел бы (хотя все еще не идеален). Я могу использовать макросы CPP, чтобы помочь абстрагировать некоторые синтаксические сахара реализации класса, которые могли бы помочь.
Вот компилируемая конструкция, которую я придумал. Есть ли что-то «не так» в этом подходе с учетом указанных выше ограничений?
#define THREAD(NAME, CONTENT) class : public Thread {\
public:\
CONTENT\
} NAME;
class Thread {
private:
uint32_t stack[256]; // 1kB stack
volatile bool _running;
public:
virtual void setup() = 0;
virtual void loop() = 0;
void start();
void stop();
uint8_t state();
static void spawn(Thread *thr);
void threadRunner();
};
void Thread::spawn(Thread *thread) {
thread->threadRunner();
}
void Thread::start() {
Thread::spawn(this);
}
void Thread::threadRunner() {
_running = true;
setup();
while (_running) {
loop();
}
}
void Thread::stop() {
_running = false;
}
uint8_t Thread::state() {
return 0;
}
THREAD(myThread,
void setup() override {
}
void loop() override {
}
)
void setup() {
myThread.start();
}
void loop() {
}
Очевидно, что на самом деле он еще ничего не делает - весь внутренний поток является отдельной проблемой и будет перенесен из некоторого существующего кода, который я написал несколько лет назад. В основном меня интересует упрощение интерфейса для конечного пользователя.