如何使用 C++ return 抽象 class
how to return an abstract class using c++
在使用 C++ 时 运行 遇到了麻烦。我已经在 SO 以及其他地方(例如:returning an abstract class from a function, and How do I make an abstract class properly return a concrete instance of another abstract class?)尝试了几个答案,但我仍然遇到了麻烦——这些似乎并不完全适合...
我有一个摘要class,一个派生class:
class AbstractClass {
virtual std::string virtMethod() = 0;
}
class Derived : public AbstractClass {
std::string virtMethod();
}
此外,我还有一个单独的 class,我正在尝试获取 return 类型的摘要 class(当然,returning 的一个实例派生 class).
我试过使用指针和引用:
AbstractClass* methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = Derived();
return &d;
}
SomeOtherDerived s = SomeOtherDerived();
return &s;
}
其中,在 Xcode 中,给我警告:
Address of stack memory associated with local variable 'd' returned
我尝试创建一个静态派生对象,但无法在调用我的 "methodFromOtherClass()."
的方法中销毁它
我也尝试过智能指针(尽管有人可能会指出我对它们的明显误用):
std::unique_ptr<AbstractClass> methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = Derived();
return std::unique_ptr<AstractClass>(&d);
}
SomeOtherDerived s = SomeOtherDerived();
return std::unique_ptr<AstractClass>(&s);
}
以上,也许不足为奇,给了我一个段错误。
我习惯于在 Java 中轻松地做到这一点...任何帮助将不胜感激。 C++ 目前对我来说不是一门非常强大的语言,所以它可能是我忽略的非常基础的东西。
在这两次尝试中,您都犯了同样的错误:返回一个指向局部变量的指针。永远不要那样做!您需要的是在堆内存 中创建 class 的新实例。
没有std::unique_ptr
:
AbstractClass* methodFromOtherClass() {
if (somethingIsTrue) {
Derived* d = new Derived();
return d;
}
SomeOtherDerived* s = new SomeOtherDerived();
return s;
}
AbstractClass *c = obj->methodFromOtherClass();
...
delete c;
或 std::unique_ptr
:
std::unique_ptr<AbstractClass> methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = new Derived();
return std::unique_ptr<AbstractClass>(d);
}
SomeOtherDerived* s = new SomeOtherDerived();
return std::unique_ptr<AbstractClass>(s);
/*
Or better, with std::make_unique():
if (somethingIsTrue) {
return std::make_unique<Derived>();
}
return std::make_unique<SomeOtherDerived>();
*/
}
std::unique_ptr<AbstractClass> c = obj->methodFromOtherClass();
...
你的基本问题(正如警告告诉你的那样)是你的函数正在返回局部变量的地址,并且当函数 returns.
时该局部变量不再存在
你的第一个版本可以改成
AbstractClass* methodFromOtherClass()
{
if (somethingIsTrue)
{
Derived *d = new Derived();
return d;
}
SomeOtherDerived *s = new SomeOtherDerived();
return s;
}
请注意,这需要调用方在完成后 delete
返回指针。
第二个版本可以改成
std::unique_ptr<AbstractClass> methodFromOtherClass()
{
if (somethingIsTrue)
{
Derived *d = new Derived();
return d;
}
SomeOtherDerived *s = new SomeOtherDerived();
return s;
}
这会解除调用者释放动态分配对象的义务。
在这两种情况下,AbstractClass
都需要一个虚拟析构函数,以避免在释放返回的对象时发生未定义的行为。
您的根本问题是您在考虑 Java 的工作方式,而 C++ 在这方面与 Java 的工作方式截然不同。停止尝试通过类比 Java 来学习 C++ - 在这种情况下,您会给自己带来更多的麻烦,而不是值得的。从 C++ 的角度来看,Java 将指针和引用的概念融合为一,因此像在 Java 中那样使用 C++ 指针和引用是 C++ 中出现问题的秘诀。
在使用 C++ 时 运行 遇到了麻烦。我已经在 SO 以及其他地方(例如:returning an abstract class from a function, and How do I make an abstract class properly return a concrete instance of another abstract class?)尝试了几个答案,但我仍然遇到了麻烦——这些似乎并不完全适合...
我有一个摘要class,一个派生class:
class AbstractClass {
virtual std::string virtMethod() = 0;
}
class Derived : public AbstractClass {
std::string virtMethod();
}
此外,我还有一个单独的 class,我正在尝试获取 return 类型的摘要 class(当然,returning 的一个实例派生 class).
我试过使用指针和引用:
AbstractClass* methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = Derived();
return &d;
}
SomeOtherDerived s = SomeOtherDerived();
return &s;
}
其中,在 Xcode 中,给我警告:
Address of stack memory associated with local variable 'd' returned
我尝试创建一个静态派生对象,但无法在调用我的 "methodFromOtherClass()."
的方法中销毁它我也尝试过智能指针(尽管有人可能会指出我对它们的明显误用):
std::unique_ptr<AbstractClass> methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = Derived();
return std::unique_ptr<AstractClass>(&d);
}
SomeOtherDerived s = SomeOtherDerived();
return std::unique_ptr<AstractClass>(&s);
}
以上,也许不足为奇,给了我一个段错误。
我习惯于在 Java 中轻松地做到这一点...任何帮助将不胜感激。 C++ 目前对我来说不是一门非常强大的语言,所以它可能是我忽略的非常基础的东西。
在这两次尝试中,您都犯了同样的错误:返回一个指向局部变量的指针。永远不要那样做!您需要的是在堆内存 中创建 class 的新实例。
没有std::unique_ptr
:
AbstractClass* methodFromOtherClass() {
if (somethingIsTrue) {
Derived* d = new Derived();
return d;
}
SomeOtherDerived* s = new SomeOtherDerived();
return s;
}
AbstractClass *c = obj->methodFromOtherClass();
...
delete c;
或 std::unique_ptr
:
std::unique_ptr<AbstractClass> methodFromOtherClass() {
if (somethingIsTrue) {
Derived d = new Derived();
return std::unique_ptr<AbstractClass>(d);
}
SomeOtherDerived* s = new SomeOtherDerived();
return std::unique_ptr<AbstractClass>(s);
/*
Or better, with std::make_unique():
if (somethingIsTrue) {
return std::make_unique<Derived>();
}
return std::make_unique<SomeOtherDerived>();
*/
}
std::unique_ptr<AbstractClass> c = obj->methodFromOtherClass();
...
你的基本问题(正如警告告诉你的那样)是你的函数正在返回局部变量的地址,并且当函数 returns.
时该局部变量不再存在你的第一个版本可以改成
AbstractClass* methodFromOtherClass()
{
if (somethingIsTrue)
{
Derived *d = new Derived();
return d;
}
SomeOtherDerived *s = new SomeOtherDerived();
return s;
}
请注意,这需要调用方在完成后 delete
返回指针。
第二个版本可以改成
std::unique_ptr<AbstractClass> methodFromOtherClass()
{
if (somethingIsTrue)
{
Derived *d = new Derived();
return d;
}
SomeOtherDerived *s = new SomeOtherDerived();
return s;
}
这会解除调用者释放动态分配对象的义务。
在这两种情况下,AbstractClass
都需要一个虚拟析构函数,以避免在释放返回的对象时发生未定义的行为。
您的根本问题是您在考虑 Java 的工作方式,而 C++ 在这方面与 Java 的工作方式截然不同。停止尝试通过类比 Java 来学习 C++ - 在这种情况下,您会给自己带来更多的麻烦,而不是值得的。从 C++ 的角度来看,Java 将指针和引用的概念融合为一,因此像在 Java 中那样使用 C++ 指针和引用是 C++ 中出现问题的秘诀。