我有一個TaskRunner
采用多型型別的模板類,Task
我想創建一個指向它們的共享指標容器。
class Task {
virtual void run() = 0;
};
class LoudTask : Task {
void run() {
std::cout << "RUNNING!" << std::endl;
}
};
class QuietTask : Task {
void run() {
std::cout << "running!" << std::endl;
}
};
template<typename T> class TaskRunner {
public:
TaskRunner<T>() {
task = std::make_unique<T>();
}
private:
std::unique_ptr<T> task;
};
using Runner = std::shared_ptr<TaskRunner<Task>>;
但是我得到error: no matching member function for call to 'push_back'
了:
std::vector<Runner> runners;
runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
runners.push_back(std::make_shared<TaskRunner<LoudTask>>());
由于:
注意:候選函式不可行:第一個引數沒有從 'shared_ptr<TaskRunner>' 到 'const shared_ptr<TaskRunner>' 的已知轉換
uj5u.com熱心網友回復:
如果TaskRunner
應該運行Task
僅繼承自的任務,您可以考慮對其進行去模板化:
#include <iostream>
#include <memory>
#include <vector>
class Task {
public:
virtual void run() = 0;
};
class LoudTask : public Task {
public:
void run() override { std::cout << "RUNNING!" << std::endl; }
};
class QuietTask : public Task {
public:
void run() override { std::cout << "running!" << std::endl; }
};
class TaskRunner {
public:
explicit TaskRunner(std::unique_ptr<Task>&& task_)
: task(std::move(task_)) {}
void run() {
if (this->task) this->task->run();
}
private:
std::unique_ptr<Task> task;
};
int main() {
using Runner = std::shared_ptr<TaskRunner>;
std::vector<Runner> runners;
runners.push_back(
std::make_shared<TaskRunner>(std::make_unique<QuietTask>()));
runners.push_back(
std::make_shared<TaskRunner>(std::make_unique<LoudTask>()));
for (auto& runner : runners) runner->run();
}
uj5u.com熱心網友回復:
實施了 IgorTandetnik 的建議,它對我有用:
#include <iostream>
#include <memory>
#include <vector>
class Task {
virtual void run() = 0;
};
class LoudTask : Task {
public:
void run() {
std::cout << "RUNNING!" << std::endl;
}
};
class QuietTask : Task {
public:
void run() {
std::cout << "running!" << std::endl;
}
};
class TaskRunnerBase
{
public:
virtual void run() =0;
};
template <class T>
class TaskRunner: public TaskRunnerBase {
public:
TaskRunner():
task(std::make_unique<T>()) {
}
void run() override
{
task->run();
}
private:
std::unique_ptr<T> task;
};
int main()
{
using Runner = std::shared_ptr<TaskRunnerBase>;
std::vector<Runner> runners;
runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
runners.push_back(std::make_shared<TaskRunner<LoudTask>>());
runners[0]->run();
runners[1]->run();
}
輸出:
running!
RUNNING!
但是請注意,TaskRunner 不需要是模板。正如上面目前實作的那樣,它有一種雙重角色:(1)任務工廠,以及(2)任務的容器和運行器。
保羅的回答很好地分開了這一點,工廠方面被移到了主要功能。
uj5u.com熱心網友回復:
這是另一個實作,它消除了對另一個繼承層次結構和 vtable 的需求,因為我們已經通過 Task 層次結構完成了它:
#include <iostream>
#include <vector>
class Task {
public:
virtual void run() = 0;
};
class LoudTask : public Task {
public:
void run() {
std::cout << "RUNNING!" << std::endl;
}
};
class QuietTask : public Task {
public:
void run() {
std::cout << "running!" << std::endl;
}
};
class TaskRunner {
public:
TaskRunner(std::unique_ptr<LoudTask> task) : m_task{ std::unique_ptr<Task>(task.release()) } {}
TaskRunner(std::unique_ptr<QuietTask> task) : m_task{ std::unique_ptr<Task>(task.release()) } {}
void run()
{
m_task->run();
}
private:
std::unique_ptr<Task> m_task;
};
using Runner = std::shared_ptr<TaskRunner>;
int main()
{
std::vector<Runner> runners;
runners.push_back(std::make_shared<TaskRunner>(std::make_unique<QuietTask>()));
runners.push_back(std::make_shared<TaskRunner>(std::make_unique<LoudTask>()));
runners[0]->run();
runners[1]->run();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/460433.html