如何使用函数(不是构造函数)将派生 class 对象分配给基 class 指针
How to assign a derived class object to a base class pointer using a function (not the constructor)
问题总结
我不知道如何通过函数(不是构造函数)使用新运算符创建派生 class 的对象,并让基 class 指针指向它。
设置
我的项目中有一个抽象基础 class 和一个派生 class:
class Base
{
// stuff
};
class Derived : public Base
{
//stuff
//constructor:
Derived(args);
};
我还有 returns 一个 Derived
对象的功能。
Derived func(args);
在某些时候,我声明了一个基class指针
Base* ptr = { nullptr };
我希望它稍后指向一个 Derived
对象。
我想要的
我想使用 func
创建一个 Derived
对象,并能够在代码后面通过指针 ptr
访问它。
到目前为止我做了什么
我知道它可以使用派生的 class 的构造函数
ptr = new Derived(args);
或者只是它的默认构造函数,如果它存在的话
ptr = new Derived;
但是,我有充分的理由不能在我的案例中使用构造函数,因为派生对象的配置更加复杂。在这种情况下,我想用函数 func
.
创建这个对象
我知道这个,
ptr = new func(args);
不起作用,因为 new
需要一个类型。我怎样才能实现这样的行为?
在此先感谢您的任何建议和有用的回复。
注意: 我正在使用 new
因为我需要访问也在其创建范围之外的 Derived
对象。
Derived * func(args)
{
Derived *p = new Derived();
// do your custom stuff:
p->x = args->i;
p->y = 3;
// return the pointer
return p;
}
// ...
ptr = func(args);
以后别忘了删除ptr。为了能够调用 Derived 的析构函数,稍后使用指向 Base 的指针,您必须将析构函数设为虚拟。
class Base
{
// ...
virtual ~Base();
};
Return 来自 func
的指针可能是最佳选择,但如果您无法修改 func
,那么 ptr = new Derived(func(args))
可能会起作用。这要求 Derived
具有复制构造函数或移动构造函数。
您可能想考虑将函数编写为
template<class T, class TA>
boost::shared_ptr<T> func(TA args) { return boost::make_shared<T>(args); }
或
template<class T, class TA>
std::shared_ptr<T> func(TA args) { return std::make_shared<T>(args); }
如果您想将其概括为任何兼容的 class 和参数类型。您可能还想对共享指针进行 typedef 以获得更好的可读性。
共享指针还将处理对象生命周期。
解决方案总结
首先感谢所有回复的人。这些建议来得非常快,非常有帮助和指导。
我不知道这是否违反了某些约定,但由于有多种非常不同的解决方案,我想总结一下。 (如果我宁愿把它作为对问题的编辑,请告诉我)。
三种方案都应该有效,我现在使用方案2。但是,我可能会在了解更多有关智能指针的知识后切换到解决方案 3。
解决方案 1 - Alex and Daniel Langr
更改函数 func
使其 return 成为一个指针。
Derived* func(args)
{
Derived *p = new Derived();
// do some complicated configuration
return p;
}
之后我可以直接用函数定义指针ptr
.
ptr = func(args);
Alex 还对如何删除 ptr
发表了一些重要评论。
虽然效果很好,但我选择不遵循这条路径,因为我想避免更改 func
的 return 值。
解决方案 2 - Mestkorn
使用复制构造函数。
这可能是最简单的解决方案。通过使用复制构造函数,我可以简单地写
ptr = new Derived( func(args) );
虽然这需要一个 copy/move 构造函数,但它与我项目中的默认复制构造函数配合得很好。我不需要实施任何新的东西。这是我目前在代码中的解决方案。
解决方案 3 - DNT
使用智能指针,更具体地说是 shared_ptr
(std::shared_ptr
或 boost::shared_ptr
。)这个概念对我来说是全新的。谢谢!
我将了解更多相关信息并可能会切换到此选项,因为它听起来像是一个 cleaner 解决方案。如果我理解正确的话,相对于其他两种解决方案的优势是我不必考虑内存泄漏或删除指针。
一旦我正确地解决了这个问题,我会回来扩展这个总结。
问题总结
我不知道如何通过函数(不是构造函数)使用新运算符创建派生 class 的对象,并让基 class 指针指向它。
设置
我的项目中有一个抽象基础 class 和一个派生 class:
class Base
{
// stuff
};
class Derived : public Base
{
//stuff
//constructor:
Derived(args);
};
我还有 returns 一个 Derived
对象的功能。
Derived func(args);
在某些时候,我声明了一个基class指针
Base* ptr = { nullptr };
我希望它稍后指向一个 Derived
对象。
我想要的
我想使用 func
创建一个 Derived
对象,并能够在代码后面通过指针 ptr
访问它。
到目前为止我做了什么
我知道它可以使用派生的 class 的构造函数
ptr = new Derived(args);
或者只是它的默认构造函数,如果它存在的话
ptr = new Derived;
但是,我有充分的理由不能在我的案例中使用构造函数,因为派生对象的配置更加复杂。在这种情况下,我想用函数 func
.
我知道这个,
ptr = new func(args);
不起作用,因为 new
需要一个类型。我怎样才能实现这样的行为?
在此先感谢您的任何建议和有用的回复。
注意: 我正在使用 new
因为我需要访问也在其创建范围之外的 Derived
对象。
Derived * func(args)
{
Derived *p = new Derived();
// do your custom stuff:
p->x = args->i;
p->y = 3;
// return the pointer
return p;
}
// ...
ptr = func(args);
以后别忘了删除ptr。为了能够调用 Derived 的析构函数,稍后使用指向 Base 的指针,您必须将析构函数设为虚拟。
class Base
{
// ...
virtual ~Base();
};
Return 来自 func
的指针可能是最佳选择,但如果您无法修改 func
,那么 ptr = new Derived(func(args))
可能会起作用。这要求 Derived
具有复制构造函数或移动构造函数。
您可能想考虑将函数编写为
template<class T, class TA>
boost::shared_ptr<T> func(TA args) { return boost::make_shared<T>(args); }
或
template<class T, class TA>
std::shared_ptr<T> func(TA args) { return std::make_shared<T>(args); }
如果您想将其概括为任何兼容的 class 和参数类型。您可能还想对共享指针进行 typedef 以获得更好的可读性。 共享指针还将处理对象生命周期。
解决方案总结
首先感谢所有回复的人。这些建议来得非常快,非常有帮助和指导。
我不知道这是否违反了某些约定,但由于有多种非常不同的解决方案,我想总结一下。 (如果我宁愿把它作为对问题的编辑,请告诉我)。
三种方案都应该有效,我现在使用方案2。但是,我可能会在了解更多有关智能指针的知识后切换到解决方案 3。
解决方案 1 - Alex and Daniel Langr
更改函数 func
使其 return 成为一个指针。
Derived* func(args)
{
Derived *p = new Derived();
// do some complicated configuration
return p;
}
之后我可以直接用函数定义指针ptr
.
ptr = func(args);
Alex 还对如何删除 ptr
发表了一些重要评论。
虽然效果很好,但我选择不遵循这条路径,因为我想避免更改 func
的 return 值。
解决方案 2 - Mestkorn
使用复制构造函数。
这可能是最简单的解决方案。通过使用复制构造函数,我可以简单地写
ptr = new Derived( func(args) );
虽然这需要一个 copy/move 构造函数,但它与我项目中的默认复制构造函数配合得很好。我不需要实施任何新的东西。这是我目前在代码中的解决方案。
解决方案 3 - DNT
使用智能指针,更具体地说是 shared_ptr
(std::shared_ptr
或 boost::shared_ptr
。)这个概念对我来说是全新的。谢谢!
我将了解更多相关信息并可能会切换到此选项,因为它听起来像是一个 cleaner 解决方案。如果我理解正确的话,相对于其他两种解决方案的优势是我不必考虑内存泄漏或删除指针。
一旦我正确地解决了这个问题,我会回来扩展这个总结。