if语句中的C ++范围问题:创建两个对象之一

时间:2012-03-08 21:57:50

标签: c++ object scope

我有一个家庭作业,我有一个基类包,还有两个派生类,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语句中的对象做我需要的东西)?

编辑:感谢大家帮忙解决问题!

5 个答案:

答案 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

http://en.cppreference.com/w/cpp/memory/unique_ptr

http://en.cppreference.com/w/cpp/memory/auto_ptr

答案 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对大多数事情很有效,在这方面它就像一个土豆。 ; - )