如果我有一个简单的程序如下: -
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。在交换机中创建的对象足够大,因此可以在每种情况下创建它们并返回对它们的引用,而不会超出范围吗?
答案 0 :(得分:3)
第一个问题的一个解决方案很明显:获取层次结构并返回基本类型。另一种解决方案是使用Variant类型,如Boost.Variant。然后,您可以将返回类型定义为:boost::variant<Wood, Glue>
。当层次结构不自然或增加复杂性时,这通常是更好的方法。另一方面,层次结构方法更容易执行,有些人不会避开Variant类附带的模板magick。
请注意,滚动自己的Variant类型可能是一项非常复杂的任务,而且更喜欢库。
你的第二个问题归结为:获得更好的编译器。最新版本的clang和gcc 4.8都报告了两种功能的警告。
答案 1 :(得分:2)
第一个问题可以通过使用第二个问题的方法来解决。这就是make Glue
和Wood
从相同的基类继承并传递对该函数的引用。这样您就不必返回局部变量的引用,并且可以返回所需的类型。
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);
}
答案 2 :(得分:1)
对于您的第一个问题,定义一个基类是一个很好的设计,从中可以获得返回的对象的可能类型。例如,让Glue和Wood派生自一个名为Carpenter
或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的编译器。
答案 3 :(得分:0)
第一个程序模板概念应用不正确
因为你必须在调用函数时传递替换T的类型。
我在编译器中编译的第二个程序,它给出了两个函数的警告