我有一个家庭作业,我有一个基类包,还有两个派生类,OvernightPackage和TwoDayPackage。在问题的某一点上,我需要根据用户输入创建这两种类型之一的对象。这显然不起作用:
if (shippingOption == OVERNIGHT) {
OvernightPackage packageObject( // Parameters entered here //);
}
else if (shippingOption == TWODAY) {
TwoDayPackage packageObject( // Parameters entered here //);
}
一旦这些if语句执行,我就超出了这些对象的范围,并且不能使用packageObject。 This post帮助我了解如果我只是创建具有不同参数的特定类型的对象,我该怎么做。但是对分配的要求是TwoDayPackage和OvernightPackage需要是不同的类。
我将如何做到这一点(除了用if语句中的对象做我需要的东西)?
编辑:感谢大家帮忙解决问题!答案 0 :(得分:4)
一种方法是使用指针:
Package *packageObject = NULL;
if (shippingOption == OVERNIGHT) {
packageObject = new OvernightPackage( // Parameters entered here //);
}
else if (shippingOption == TWODAY) {
packageObject = new TwoDayPackage( // Parameters entered here //);
}
答案 1 :(得分:3)
A
类型的变量实际上不能是派生类型,因此(正如您所注意到的)您不能只声明Package packageObject;
并指定OvernightPackage
或{{1}它(它们将被切片)。
但是,指向TwoDayPackage
的指针可以指向从A
派生的类的实例。对于引用和(大多数类型的)智能指针也是如此。
答案 2 :(得分:2)
喜欢这样
#include <memory>
:::
std::unique_ptr<Package> package;
if(shippingOption == OVERNIGHT)
package.reset(new OvernightPackage(params));
else if (shippingOption == TWODAY)
package.reset(new TwoDayPackage(params));
package->member;
package->member_function();
如果您无权访问C ++ 11(请参阅编译器),您可以始终使用boost::scoped_ptr
,或者如果您真的需要std::auto_ptr
。 (如果你有gcc / g ++然后尝试使用-std = c ++ 0x进行编译)
然后通过这种方式优于其他列出的方法的优点是内存由RAII语义管理,这与现代C ++设计一致。
http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
答案 3 :(得分:2)
答案是指针。
Package *packageConstructor(int type)
{
switch (type) {
case OVERNIGHT: return new OvernightPackage(/* ... */);
case TWODAY: sleep(2 * 86400); /* :) :) :) */ return new TwoDayPackage(/* ... */);
default: // unrecognized type: handle somehow: return NULL, or throw exception
}
}
一旦有了指针,就必须担心异常安全问题。最好使用一些智能指针容器而不是原始指针。
答案 4 :(得分:2)
操作代码:
if (shippingOption == OVERNIGHT) {
OvernightPackage packageObject( // Parameters entered here //);
}
else if (shippingOption == TWODAY) {
TwoDayPackage packageObject( // Parameters entered here //);
}
// Presumably, process the package here.
您可以这样做,只使用自动分配,这是绝对最好的 - 最简单,最安全,最有效 - 适用时:
void process( Package const& package )
{
// Process the package here.
}
void foo()
{
// ... whatever, then:
switch( shippingOption )
{
case overnight:
process( OvernightPackage( blah ) );
break;
case twoDay:
process( TwoDayPackage( blah ) );
break;
default:
assert( false ); // Should never get here.
}
}
如果不可能,那么您可以使用动态分配包对象。麻烦的是,作为一个初学者,你可能不太了解上述是否几乎不可能(尽管可以很容易地看到它确实可能)。无论如何,对于动态分配,使用智能指针,例如C ++ 11 std::shared_ptr
:
typedef std::shared_ptr<Package> PackagePtr;
PackagePtr foo( blah, blah, arguments )
{
// ... whatever, then:
switch( shippingOption )
{
case overnight:
return PackagePtr( new OvernightPackage( blah ) );
case twoDay:
return PackagePtr( new TwoDayPackage( blah ) );
default:
assert( false ); // Should never get here.
}
}
当您获得更多经验时,您应该努力始终使用可以完成工作的大多数受限制的智能指针,例如可以是std::unique_ptr
。因为将所有权转移到共享智能指针很容易,但很难将其转移回所有权指针。然而,作为初学者,你会发现std::shared_ptr
对大多数事情很有效,在这方面它就像一个土豆。 ; - )