C++ 从函数返回多个类型引用并将它们转换为我们需要的类型
C++ Returning multiple type references from function and casting them to a type that we need
我需要一个 return 是变量的函数,但我不想指定它将 return 的变量类型(这将在以后的使用中确定)。
// unknownType is a char, because it uses only one byte of memory
typedef char unknownType;
unknownType& func (bool typeSelector) {
// let's say we want to return double and int type
double dblVal = 3.5;
int intVal = 5;
// return type depends on typeSelector's state
if (typeSelector == true)
return (unknownType&)dblVal;
else
return (unknownType&)intVal;
}
然后我会这样使用它:
double dblVal = (double&) func(true);
std::cout << dblVal << std::endl;
std::cout << (int&) func(false);
上面的代码工作得很好(如果我不尝试 return 更复杂的对象,例如 std::string,但这对我的需要来说没问题);我已经在 linux 和 windows 上编译了它。但我不确定它是否是我问题的便携式解决方案。
我的问题是:此代码中是否有任何内容会破坏我的程序并使其变得无用?从性能方面来看,它的效率如何?
编辑:为什么我不能在这里使用模板
我有一个基地class:
class Base {
public:
virtual unknownType& getValue () = 0;
};
然后是几个派生的 classes,它们包含不同类型的变量:
class DerivedDbl : public Base {
private:
double value;
public:
DerivedDbl (double val) : value(val) {}
unknownType& getValue () {
double toReturn = value;
return (unknownType&)toReturn;
}
};
class DerivedInt : public Base {
private:
int value;
public:
DerivedInt (int val) : value(val) {}
unknownType& getValue () {
int toReturn = value;
return (unknownType&)toReturn;
}
};
然后我有一个 class,它存储派生的 classes 并对它们进行一些操作:
class Storage {
private:
std::vector <Base*> vec;
public:
void operator+= (Base& obj) { vec.push_back(&obj); }
unknownType& operator[] (int ID) {
return vec[ID]->getValue();
}
};
而且我有时希望能够获取存储的派生 classes 的变量值(我知道我添加了哪个,所以我知道它们的类型),但我不认为创建为每个单独的 getter 方法并不是获得它们的优雅方式,这样的代码对我来说看起来更清晰:
DerivedDbl derivedDbl(3.5);
DerivedInt derivedInt(5);
Storage storage;
storage += derivedDbl;
storage += derivedInt;
std::cout << (double&)storage[0] << std::endl;
std::cout << (int&)storage[1];
但也许我遗漏了一些东西并且可以使用不同的方法做同样的事情(我已经尝试过模板但没有想出任何好主意,你们劝阻无效指针,联合和结构需要更多内存)。
您正在 return引用局部变量。这有时似乎可行,但它是未定义的行为,并且会在某些时候严重破坏您的程序。
如果你真的需要一个虚函数,它应该 return 某种类型隐藏 class(例如 boost::any)。然后您可以将 returned 值转换为正确的类型。
或者,您可以使函数成为非虚函数,然后从基类型转换为适当的派生类型。派生的 classes 可以 return 您真正想要的类型。
模板可用于促进此行为,例如:
class Base
{
public:
virtual ~Base() { }
};
template<class T>
class ValueType : public Base
{
public:
explicit ValueType(T value): value(value) { }
T& GetValue()
{
return value;
}
private:
T value;
}
struct Storage
{
std::vector<Base*> objects;
template<class T>
T& GetValue(unsigned int index)
{
auto derived = dynamic_cast<ValueType<T>*>(objects[index]);
return derived->GetValue();
}
};
编辑:更改了访问控制。
我需要一个 return 是变量的函数,但我不想指定它将 return 的变量类型(这将在以后的使用中确定)。
// unknownType is a char, because it uses only one byte of memory
typedef char unknownType;
unknownType& func (bool typeSelector) {
// let's say we want to return double and int type
double dblVal = 3.5;
int intVal = 5;
// return type depends on typeSelector's state
if (typeSelector == true)
return (unknownType&)dblVal;
else
return (unknownType&)intVal;
}
然后我会这样使用它:
double dblVal = (double&) func(true);
std::cout << dblVal << std::endl;
std::cout << (int&) func(false);
上面的代码工作得很好(如果我不尝试 return 更复杂的对象,例如 std::string,但这对我的需要来说没问题);我已经在 linux 和 windows 上编译了它。但我不确定它是否是我问题的便携式解决方案。
我的问题是:此代码中是否有任何内容会破坏我的程序并使其变得无用?从性能方面来看,它的效率如何?
编辑:为什么我不能在这里使用模板
我有一个基地class:
class Base {
public:
virtual unknownType& getValue () = 0;
};
然后是几个派生的 classes,它们包含不同类型的变量:
class DerivedDbl : public Base {
private:
double value;
public:
DerivedDbl (double val) : value(val) {}
unknownType& getValue () {
double toReturn = value;
return (unknownType&)toReturn;
}
};
class DerivedInt : public Base {
private:
int value;
public:
DerivedInt (int val) : value(val) {}
unknownType& getValue () {
int toReturn = value;
return (unknownType&)toReturn;
}
};
然后我有一个 class,它存储派生的 classes 并对它们进行一些操作:
class Storage {
private:
std::vector <Base*> vec;
public:
void operator+= (Base& obj) { vec.push_back(&obj); }
unknownType& operator[] (int ID) {
return vec[ID]->getValue();
}
};
而且我有时希望能够获取存储的派生 classes 的变量值(我知道我添加了哪个,所以我知道它们的类型),但我不认为创建为每个单独的 getter 方法并不是获得它们的优雅方式,这样的代码对我来说看起来更清晰:
DerivedDbl derivedDbl(3.5);
DerivedInt derivedInt(5);
Storage storage;
storage += derivedDbl;
storage += derivedInt;
std::cout << (double&)storage[0] << std::endl;
std::cout << (int&)storage[1];
但也许我遗漏了一些东西并且可以使用不同的方法做同样的事情(我已经尝试过模板但没有想出任何好主意,你们劝阻无效指针,联合和结构需要更多内存)。
您正在 return引用局部变量。这有时似乎可行,但它是未定义的行为,并且会在某些时候严重破坏您的程序。
如果你真的需要一个虚函数,它应该 return 某种类型隐藏 class(例如 boost::any)。然后您可以将 returned 值转换为正确的类型。
或者,您可以使函数成为非虚函数,然后从基类型转换为适当的派生类型。派生的 classes 可以 return 您真正想要的类型。
模板可用于促进此行为,例如:
class Base
{
public:
virtual ~Base() { }
};
template<class T>
class ValueType : public Base
{
public:
explicit ValueType(T value): value(value) { }
T& GetValue()
{
return value;
}
private:
T value;
}
struct Storage
{
std::vector<Base*> objects;
template<class T>
T& GetValue(unsigned int index)
{
auto derived = dynamic_cast<ValueType<T>*>(objects[index]);
return derived->GetValue();
}
};
编辑:更改了访问控制。