【发布时间】:2021-12-31 01:03:45
【问题描述】:
我对多态性很熟悉,但对 C++ 尤其是模板还很陌生。我必须使用我无法更改的代码(使用框架、所有事件和模板化事件侦听器)和我控制下的代码(下例中的客户端)来跟踪情况。
#include <string>
#include <iostream>
#include <vector>
class EventBase {
public:
virtual std::string getData() const = 0;
};
class EventA : public EventBase {
public:
std::string getData() const override {
return "Event A";
}
};
class EventB : public EventBase {
public:
std::string getData() const override {
return "Event B";
}
};
template<class T_Event>
class IEventHandler
{
public:
virtual void onEvent(const T_Event& e) = 0;
virtual void onError() = 0;
};
class ClientBase {
public:
virtual void startReceiving() = 0;
virtual void stopReceiving() {
std::cout << "ClientBase::stopReceiving" << std::endl;
}
};
class ClientA : public ClientBase, public IEventHandler<EventA> {
public:
void onEvent(const EventA& e) override {
std::cout << "ClientA::onEvent - e.getData()= " << e.getData() << std::endl;
};
void onError() override {
std::cout << "ClientA::onError" << std::endl;
};
void startReceiving() override {
std::cout << "ClientA::startReceiving" << std::endl;
};
};
class ClientB : public ClientBase, public IEventHandler<EventB> {
public:
void onEvent(const EventB& e) override {
std::cout << "ClientB::onEvent - e.getData()= " << e.getData() << std::endl;
};
void onError() override {
std::cout << "ClientB::onError" << std::endl;
};
void startReceiving() override {
std::cout << "ClientB::startReceiving" << std::endl;
};
};
int main(int, char**) {
//User Code
ClientA ca;
ClientB cb;
std::vector<ClientBase*> baseClients;
baseClients.push_back(&ca);
baseClients.push_back(&cb);
for(const auto client : baseClients){
client->startReceiving();
}
//Framework Code
EventA a;
EventB b;
std::vector<IEventHandler<EventA>*> eventHandlersA;
std::vector<IEventHandler<EventB>*> eventHandlersB;
eventHandlersA.push_back(&ca);
eventHandlersA[0]->onError();
eventHandlersA[0]->onEvent(a);
eventHandlersB.push_back(&cb);
eventHandlersB[0]->onError();
eventHandlersB[0]->onEvent(b);
//User Code
for(const auto client : baseClients){
client->stopReceiving();
}
}
请看这里:https://onlinegdb.com/2MYQhC2G5
我现在想做的是有一个onError 的通用默认实现。
为此,我至少尝试了四种方法。只有第二个有效。如果这种方法 2 实际上是实现它的方法,那么听取 C++ 专家的意见会很高兴。
方法 1
只需将onError 放入ClientBase 并将其从派生客户端中删除即可。
class ClientBase {
public:
virtual void startReceiving() = 0;
virtual void stopReceiving() {
std::cout << "ClientBase::stopReceiving" << std::endl;
}
virtual void onError(){
std::cout << "ClientBase::onError" << std::endl;
}
};
class ClientA : public ClientBase, public IEventHandler<EventA> {
public:
void onEvent(const EventA& e) override {
std::cout << "ClientA::onEvent - e.getData()= " << e.getData() << std::endl;
};
void startReceiving() override {
std::cout << "ClientA::startReceiving" << std::endl;
};
};
编译时失败
error: variable type 'ClientA' is an abstract class
note: unimplemented pure virtual method 'onError' in 'ClientA'
好的,它是抽象的,因为它没有实现 IEventHandler<EventA> 所需的方法
方法 2
修复ClientA中未实现的方法但调用超类方法实现:
class ClientA : public ClientBase, public IEventHandler<EventA> {
public:
void onEvent(const EventA& e) override {
std::cout << "ClientA::onEvent - e.getData()= " << e.getData() << std::endl;
};
void onError() override {
ClientBase::onError();
};
void startReceiving() override {
std::cout << "ClientA::startReceiving" << std::endl;
};
};
有效,但在幕后我认为其他事情正在发生,然后是最初的预期(可能更多的是委托然后是继承)。
可能会乱用模板?
方法3:从派生客户端中删除IEventHandler
class ClientBase : public IEventHandler<EventBase> {
public:
virtual void startReceiving() = 0;
virtual void stopReceiving() {
std::cout << "ClientBase::stopReceiving" << std::endl;
}
virtual void onError(){
std::cout << "ClientBase::onError" << std::endl;
}
virtual void onEvent(const EventBase& e) = 0;
};
class ClientA : public ClientBase {
public:
void onEvent(const EventA& e) override {
std::cout << "ClientA::onEvent - e.getData()= " << e.getData() << std::endl;
};
void startReceiving() override {
std::cout << "ClientA::startReceiving" << std::endl;
};
};
构建系统讨厌我:
error: non-virtual member function marked 'override' hides virtual member function
note: hidden overloaded virtual function 'ClientBase::onEvent' declared here: type mismatch at 1st parameter ('const EventBase &' vs 'const EventA &')
error: variable type 'ClientA' is an abstract class
note: unimplemented pure virtual method 'onEvent' in 'ClientA' - virtual void onEvent(const EventBase& e) = 0;
好的,只有当签名完全匹配时,您才能覆盖方法。
方法 4:将ClientBase 模板化
template<class T_Event>
class ClientBase {
public:
virtual void startReceiving() = 0;
virtual void stopReceiving() {
std::cout << "ClientBase::stopReceiving" << std::endl;
}
virtual void onError(){
std::cout << "ClientBase::onError" << std::endl;
}
virtual void onEvent(const T_Event& e) = 0;
};
class ClientA : public ClientBase<EventA> {
public:
void onEvent(const EventA& e) override {
std::cout << "ClientA::onEvent - e.getData()= " << e.getData() << std::endl;
};
void startReceiving() override {
std::cout << "ClientA::startReceiving" << std::endl;
};
};
再次,没有成功。这一次我跟踪客户的结构会崩溃:
std::vector<ClientBase*> baseClients; ----> error: use of class template 'ClientBase' requires template arguments
eventHandlersA.push_back(&ca); ---> error: no matching member function for call to 'push_back'
对于如何实现最初的目标,您还有什么想法吗?还是坚持方法 2 是一个好的解决方案?
【问题讨论】:
标签: c++ templates polymorphism