我希望C++类中的属性是来自特定类继承的未实例化类。然后,此类 heirachy 的所有成员都将实现相同的方法,这意味着我可以实例化对象,然后在情况需要时使用该方法。这里有一些代码(不能编译(演示了我的意思:
#include <iostream>
using namespace std;
class Event {
public:
Event() = default;
virtual void go() = 0;
};
class EventA : Event {
public:
EventA() = default;
void go(){
cout << "Running event A"<< endl;
}
};
class EventB : Event {
public:
EventB() = default;
void go(){
cout << "Running event B"<< endl;
}
};
class Situation{
private:
Event* current_event = &EventA; //Problematic code: EventA does not refer to a value
public:
Situation() = default;
void setEvent(Event* event){
current_event = event;
}
void runEvent(){
current_event.go();
}
};
int main() {
Situation situation;
situation.runEvent();
situation.setEvent(&EventB);
situation.runEvent();
return 0;
};
不,不能形成指向类的指针,也不能在没有类实例(对象(的情况下调用 [非静态] 成员函数。
您可能应该std::make_unique
要使用的类型的实例。
不要忘记给你的基础一个虚拟析构函数,因为你正在做多态的事情。
静态替代方案是std::variant
.
在两个地方,您似乎正在做可以描述为尝试从类型中获取指针的操作:
Event* current_event = &EventA;
和
situation.setEvent(&EventB);
这是行不通的,在C++中并不是一件真正具有正确含义的事情。您正在尝试做的事情可以通过我能想到的 3 种不同方式实现。
方法 1:可以有一个函数指针,而不是一个类,并将函数指针作为参数传递:
#include <iostream>
using namespace std;
void eventA_go(){
cout << "Running event A"<< endl;
}
void eventB_go(){
cout << "Running event B"<< endl;
}
class Situation{
private:
using EventFunctionPtr = void (*)();
EventFunctionPtr current_event = &eventA_go;
public:
Situation() = default;
void setEvent(EventFunctionPtr event){
current_event = event;
}
void runEvent(){
current_event();
}
};
int main() {
Situation situation;
situation.runEvent();
situation.setEvent(&eventB_go);
situation.runEvent();
return 0;
};
方法 2:您可以通过在Situation
类中允许任何类型的可调用对象(而不仅仅是函数指针(来使此代码更加通用:
#include <iostream>
#include <functional>
using namespace std;
void eventA_go(){
cout << "Running event A"<< endl;
}
void eventB_go(){
cout << "Running event B"<< endl;
}
class Situation{
private:
std::function<void ()> current_event = eventA_go;
public:
Situation() = default;
template <typename F>
void setEvent(F&& event){
current_event = event;
}
void runEvent(){
current_event();
}
};
int main() {
Situation situation;
situation.runEvent();
situation.setEvent(&eventB_go);
situation.runEvent();
return 0;
};
方法3:您可以回到最初的想法,即拥有一个必须实现以提供go()
方法的基类,但在这种情况下,您实际上必须确保要调用的对象确实存在。一种可能的方法是使用std::unique_ptr
:
#include <iostream>
#include <memory>
using namespace std;
class Event {
public:
Event() = default;
virtual ~Event() = default;
virtual void go() = 0;
};
class EventA : public Event {
public:
EventA() = default;
void go(){
cout << "Running event A"<< endl;
}
};
class EventB : public Event {
public:
EventB() = default;
void go(){
cout << "Running event B"<< endl;
}
};
class Situation{
private:
std::unique_ptr<Event> current_event = std::make_unique<EventA>();
public:
Situation() = default;
void setEvent(std::unique_ptr<Event>&& event){
current_event = std::move(event);
}
void runEvent(){
current_event->go();
}
};
int main() {
Situation situation;
situation.runEvent();
situation.setEvent(std::make_unique<EventB>());
situation.runEvent();
return 0;
};
请注意,在这种情况下,抽象类的析构函数必须是virtual
的,并且继承必须是公共的。
您似乎对类和变量感到困惑。situation.runEvent();
哪个对象上运行?我认为您想从Event
公开派生类并在需要时初始化current_event
。你不需要做任何像current_event = &EventB
.C++根据动态指向的内容自动确定需要调用current_event
函数。以下是我认为你的意思:
#include <cassert>
#include <iostream>
class Event {
public:
virtual void go() = 0;
virtual ~Event() = default; // Don't forget the virtual destructor
};
class EventA : public Event {
public:
void go() override { std::cout << "Running event A" << std::endl; }
};
class EventB : public Event {
public:
void go() override { std::cout << "Running event B" << std::endl; }
};
class Situation {
private:
Event* current_event = nullptr;
public:
void setEvent(Event* event) { current_event = event; }
void runEvent() {
assert(current_event);
current_event->go();
}
};
int main() {
Situation situation;
EventA a;
EventB b;
situation.setEvent(&a);
situation.runEvent();
situation.setEvent(&b);
situation.runEvent();
}