我想为返回消息的类创建一个接口。我的问题是,有时返回一个字符串会更好,有时返回一个const string&会更好。为继承类提供选择返回类型的可能性的最佳方法是什么?
struct Verbose{
// my message is a class member
virtual const string& getMsg()const=0;
// my message is created in the function
virtual string getMsg()const=0;
};
我想要这样的东西,而不是这个接口,以便提供这种灵活性
struct Verbose{
virtual myPrintableType getMsg()const=0;
};
1
3 个回答
3
您可以对成员函数使用
struct Verbose{
virtual const std::string& getMsg() const& = 0;
virtual std::string getMsg() const&& = 0;
};
struct Derived: Verbose {
std::string s{"xxx"};
const std::string& getMsg()const& {
std::cout << "const string&\n";
return s;
}
std::string getMsg()const&& {
std::cout << "string\n";
return "yyy";
}
};
仅当您的对象是左值时才会调用第一个版本,即通过 const 引用返回成员字段被认为是安全的。第二个版本将被称为 r 值。
Derived d;
std::cout << d.getMsg() << std::endl; // calls 1st overload
std::cout << Derived{}.getMsg() << std::endl; // calls 2nd overload
这是假设您希望根据值类别有不同的行为。如果情况并非如此,并且您需要为同一值类别使用不同的返回类型,那么您需要 2 个不同的函数。
1
-
1这正是我一直在寻找的!谢谢 :)
–
|
该函数无法选择——您只能返回一种类型。重载(具有不同类型的相同函数名称)仅适用于参数类型 – 是的,如果您的函数采用不同的参数类型,它们也可能返回不同的结果类型。
但是,如果调用者可以做出决定,那么它当然可以调用一个或另一个函数。就像我有这个API:
template <typename T> const T& get() const requires (!std::is_scalar_v<T>);
template <typename T> T get() const requires (std::is_scalar_v<T>);
当然,我只能这样做,因为调用者知道它会得到什么。我最终可能会删除标量版本。
就您而言,消息通常只是基类,并且您通常可以始终返回std:unique_ptr
或std::shared_ptr
(取决于消息的工作方式)。当然,如果它真的只是字符串,那么就决定一个版本。
|
不幸的是,不可能完全按照您所描述的操作,因为基于返回类型的重载是不可能的。不过你可以使用常量
struct Verbose{
virtual const string& getMsg()const=0;
//Either return string
virtual string getMsg()=0;
//Or a reference
virtual string& getMsg()=0;
};
如果要在调用代码中使用字符串的副本,可以使用返回常量引用的 const 函数。此函数重载更加“通用”,因为它允许用户决定如何处理字符串,并且不会强制他们执行复制。
|
–
|