【问题标题】:C++ Returning multiple type references from function and casting them to a type that we needC++ 从函数返回多个类型引用并将它们转换为我们需要的类型
【发布时间】:2015-01-14 13:20:26
【问题描述】:

我需要一个返回变量的函数,但是我不想指定它将返回什么类型的变量(这是以后使用时确定的)。

// 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);

上面的代码工作得很好(如果我不想返回更复杂的对象,例如 std::string,但这对我的需要来说没问题);我已经在linux和windows上编译过它。但我不相信它是否是我问题的便携式解决方案。

我的问题是:这段代码中是否有任何东西可以破坏我的程序并使其无用?就性能而言,它的效率如何?

编辑:为什么我不能在这里使用模板

我有一个基类:

class Base {
public:
    virtual unknownType& getValue () = 0;
};

然后是几个派生类,它们包含不同的类型变量:

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 Storage {
private:
    std::vector <Base*> vec;
public:
    void operator+= (Base& obj) { vec.push_back(&obj); }

    unknownType& operator[] (int ID) {
        return vec[ID]->getValue();
    }
};

而且我有时希望能够获取存储的派生类的变量值(我知道我添加了哪一个,所以我知道它们的类型),但我不认为为每个创建单独的 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];

但也许我错过了一些东西,并且可以使用不同的方法做同样的事情(我尝试过模板并没有提出任何好的想法,你们劝阻了 void 指针、联合和结构需要更多内存)。

【问题讨论】:

  • “上面的代码工作得很好” 我严重怀疑这一点。您刚刚遇到了未定义的行为。不要使用这样的演员表,而是使用模板代替。
  • @quantdev:问题是,我不能。我稍后会编辑这篇文章来解释原因。
  • πάντα ῥεῖ:嗯,它按预期工作,打印 3.5 和 5...
  • @Jezor 在获取引用和打印值之间进行一些堆栈更改操作。然后你会发现它不起作用。要“让它工作”,您可以做的最好的事情是声明函数static 中使用的intdouble 变量。
  • 这通常是X-Y problem

标签: c++ function reference return return-type


【解决方案1】:

您正在返回对局部变量的引用。这有时似乎有效,但它是未定义的行为,并且会在某些时候严重破坏您的程序。

如果你真的需要一个虚函数,它可能应该返回某种类型的隐藏类(例如 boost::any)。然后您可以将返回的值转换为正确的类型。

或者,您可以使函数成为非虚拟函数,并从基类型转换为适当的派生类型。然后派生类可以只返回您真正想要的类型。

可以使用模板来促进这种行为,例如:

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();
    }
};

编辑:更改访问控制。

【讨论】:

  • 我考虑过自动说明符,但我没有与 C++11 兼容的编译器 - 我想我得弄一个,谢谢!
  • @Jezor 注意auto对于代码来说根本不是必需的,如果你没有c++11,你可以用ValueType&lt;T&gt;*替换它。
  • @user2079303 你能编辑你的代码来匹配我的吗?我正在尝试以我想要的方式实现它,但我遇到了错误(比如“‘Base’是‘ValueType’的一个不可访问的基础”)。我会非常感谢!
  • @Jezor 您可能打算将评论指向写答案的人(我知道,我们的用户名非常相似 :) 就是说,错误听起来您忘记公开继承。
  • @Jezor 正如 user2079303 所说,结构默认公开继承,类私有继承。因此,如果您已将 ValueType 声明为一个类,则需要显式地执行 : public Base。我已更改代码以匹配。
猜你喜欢
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 2017-07-11
相关资源
最近更新 更多