是否可以使用指向未实例化对象的指针作为 C++ 中的变量?
Is it possible to use a pointer to an uninstantiated object as a variable in C++?
我希望 C++ class 中的属性是来自特定 class 继承权的未实例化 class。然后,这个 class 家族的所有成员都将实现相同的方法,这意味着我可以实例化该对象,然后在情况需要时使用该方法。这里有一些代码(不能编译)证明了我的意思:
#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;
};
不,您不能形成指向 classes 的指针,并且您不能在没有 class 实例(对象)的情况下调用 [非静态] 成员函数。
您可能应该 std::make_unique
您要使用的类型的实例。
不要忘记给你的基类一个虚拟析构函数,因为你正在做多态性的事情。
静态替代方案是 std::variant
。
您似乎对 类 和变量感到困惑。 situation.runEvent();
运行 会在哪个对象上?我想你想 publicly 从 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();
}
在两个地方,您似乎在做可以被描述为试图从类型中获取指针的事情:
Event* current_event = &EventA;
和
situation.setEvent(&EventB);
这是行不通的,在 C++ 中也不是真正具有适当意义的东西。您尝试做的事情可以通过我能想到的 3 种不同的方式实现。
方法 1:您可以使用函数指针代替 class,并将函数指针作为参数传递:
#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
class 中允许任何类型的可调用对象,而不仅仅是函数指针:
#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:您可以回到最初的想法,即必须实现一个基础 class 以提供 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;
};
注意,在这种情况下,抽象class的析构函数必须是virtual
,继承必须是public.
我希望 C++ class 中的属性是来自特定 class 继承权的未实例化 class。然后,这个 class 家族的所有成员都将实现相同的方法,这意味着我可以实例化该对象,然后在情况需要时使用该方法。这里有一些代码(不能编译)证明了我的意思:
#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;
};
不,您不能形成指向 classes 的指针,并且您不能在没有 class 实例(对象)的情况下调用 [非静态] 成员函数。
您可能应该 std::make_unique
您要使用的类型的实例。
不要忘记给你的基类一个虚拟析构函数,因为你正在做多态性的事情。
静态替代方案是 std::variant
。
您似乎对 类 和变量感到困惑。 situation.runEvent();
运行 会在哪个对象上?我想你想 publicly 从 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();
}
在两个地方,您似乎在做可以被描述为试图从类型中获取指针的事情:
Event* current_event = &EventA;
和
situation.setEvent(&EventB);
这是行不通的,在 C++ 中也不是真正具有适当意义的东西。您尝试做的事情可以通过我能想到的 3 种不同的方式实现。
方法 1:您可以使用函数指针代替 class,并将函数指针作为参数传递:
#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
class 中允许任何类型的可调用对象,而不仅仅是函数指针:
#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:您可以回到最初的想法,即必须实现一个基础 class 以提供 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;
};
注意,在这种情况下,抽象class的析构函数必须是virtual
,继承必须是public.