【发布时间】:2020-06-24 07:07:38
【问题描述】:
这是我目前正在研究的一个玩具示例
class Foo
{
private:
std::string s;
std::vector<std::string> v;
public:
// Foo constructors and other big 3
std::string const& strmember() const;
std::vector<std::string> const& vecmember() const;
std::vector<std::string>& vecmember();
};
到目前为止一切顺利。要求来了,我必须添加重载并更改 Foo 的胆量,如下所示
class Foo
{
private:
std::u16string ssname;
std::vector<std::u16string> vvname;
public:
// Foo constructors and other big 3
std::string const& strmember() const;
std::vector<std::string> const& vecmember() const;
std::vector<std::string>& vecmember();
std::u16string const& strmember(int) const;
std::vector<std::u16string> const& vecmember(int) const;
std::vector<std::u16string>& vecmember(int);
};
我必须保留老成员并为新成员添加重载,以便老客户不会中断。执行适当的字符转换,以便将旧的构造函数委托给新的构造函数,并根据新设计更改提供的成员。
如下实现这些成员
std::string const& Foo::strmember() const
{
const auto& name = char_convert(ssname);
return name;
}
std::vector<std::string>& Foo::vecmember()
{
return vecmember();
}
std::vector<std::string>& Foo::vecmember()
{
std::vector<std::string> result;
std::transform(vvname.begin(),vvname.end(),std::back_inserter(result),[] (const std:u16string& in) -> std::string
{
return char_convert(in);
});
return result;
}
std::u16string const& Foo::strmember(int) const
{
return ssname;
}
std::vector<std::u16string> const& Foo::vecmember(int) const
{
return vvname;
}
std::vector<std::u16string>& Foo::vecmember(int)
{
return vvname;
}
当我尝试编译更改的代码时,编译器会给出以下警告和错误
error: reference to local variable ‘result’ returned [-Werror=return-local-addr]
std::vector<std::string> result;
^~~~~~
foo.cpp: In member function ‘const string& foo::strmember() const’:
foo.cpp: error: function returns address of local variable [-Werror=return-local-addr]
return name;
^~~~
foo.cpp: note: declared here
const auto& name = char_convert(ssname);
^
cc1plus: all warnings being treated as errors
我该如何解决这个问题?我无法更改界面,因为它可能会破坏单元测试和客户端。
如何提供vecmember() 和strmember() 函数的mutator 和accessor 版本?
【问题讨论】:
-
如果你的成员函数返回一个引用,那么,正如错误消息所说,你不能返回一个本地(严格来说是允许的,但会导致未定义的行为,所以你很幸运你的编译器是报告错误)。一种方法是保留旧的类成员,并返回对它们的引用。如果您坚持删除这些成员并通过引用返回.... 好吧,您不能吃蛋糕也不能吃。另一种选择是更改函数,以便它们按值返回。
-
根据您的客户如何使用您的访问器,代理对象可能是一种变通方法。不过非常值得怀疑。