0

如果我有一个简单的程序如下: -

class Program
{
    public:
       my_func(void)                 \\ What return type do I use here??
       {
            switch (i)               \\ assume i comes from somewhere...
            {
                case 1:
                {
                    Glue g;
                    g.init();
                    return g;
                }
                case 2:
                {
                    Wood w;
                    w.init();
                    return w;
                }
                ....
            }
        }
}

有人可以告诉我如何将此函数的返回类型设置为在其中一个开关案例中创建的对象吗?同样由于时间限制,我不能使用 new/delete 来创建对象,否则我只会返回一个 void* ptr。在 switch 中创建的对象足够大,那么是否可以在每种情况下创建它们并返回对它们的引用,而不会超出范围?

4

4 回答 4

3

第一个问题的一个解决方案是显而易见的:获取层次结构并返回基本类型。另一种解决方案是使用 Variant 类型,例如Boost.Variant。然后你可以将你的返回类型定义为:boost::variant<Wood, Glue>。当层次结构不自然或会增加复杂性时,这通常是更可取的方法。另一方面,层次方法执行起来更简单,有些人不会回避 Variant 类附带的模板魔法。

请注意,滚动您自己的 Variant 类型可能是一项非常复杂的工作,并且更喜欢使用库。

您的第二个问题归结为:获得更好的编译器。最新版本的 clang 和 gcc 4.8 都报告了这两个函数的警告。

于 2013-04-29T17:05:55.893 回答
2

第一个问题可以通过使用第二个问题的方法来解决。即从同一个基类生成GlueWood继承并传递对函数的引用。这样你就不必返回一个局部变量的引用,你可以返回你想要的类型。

struct Obj {

    virtual void init() { cout << "Obj"; }
};

struct Wood : public Obj {
    virtual void init() { cout << "Wood"; }
};


struct Glue : public Obj {
    virtual void init() { cout << "Glue"; }
};

struct Program {

    // Pass by reference the actual object. You want it created it here?
    // Why just create it outside. i.e move your case to the place where you know what i 
    // is. It doesn't have to be created here.
    void foo(Obj& o) { 
        o.init(); 
    }
};



int main()
{
    Program p;
    Obj* ref_p;

    // Move your case here.
    //case
        Wood w;
        ref_p = &w;
    // 
        //Glue g;
        //ref_p = &g;

    p.foo(*ref_p);
}
于 2013-04-29T16:32:29.330 回答
1

对于您的第一个问题,最好定义一个基类,从该基类中派生返回的对象的可能类型。例如,让 Glue 和 Wood 派生自一个名为Carpenteror的类CarpenterObject,您需要在其中包含一个指示该对象实际是什么的指示符。

class Carpenter
{

public:

    static const int UNKNOWN = -1; //example only
    static const int GLUE = 0;
    static const int WOOD = 1;

    virtual int Type() { return UNKNOWN; }

    Carpenter* GetSomething();

};

class Glue: public Carpenter
{
    virtual int Type() { return Carpenter::GLUE; }
};

class Wood: public Carpenter
{
    virtual int Type() { return Carpenter::WOOD; }
};

Carpenter* Carpenter::GetSomething()
{
    Glue* g = new Glue();
    Wood* w = new Wood();

    return g; // or w
}

void main()
{
    Carpenter p;
    cout<<p.GetSomething()->Type();
}

我认为第二个问题处理的是警告而不是错误(它对我正常工作),但我使用的是 Visual Studio 2012 的编译器。

于 2013-04-29T16:42:07.753 回答
0

第一个程序模板概念应用不正确

因为您必须在调用函数时传递替换 T 的类型。

我在编译器中编译的第二个程序,它对这两个函数都给出了警告

于 2013-04-29T16:26:45.047 回答