所以我在c ++中有一个虚拟流媒体接口
class KxStream
{
public:
virtual KxStream& operator<< ( u32 num ) = 0;
};
Run Code Online (Sandbox Code Playgroud)
它拥有大量基本的<<运算符,适用于所有内置类型.我刚刚列出了一个.
然后我有一些实现流接口的类.像这样:
class KxCbuf : public KxStream
{
public:
KxStream& operator<<( u32 num );
}
Run Code Online (Sandbox Code Playgroud)
因此在KxCbuf中有一个流接口的实现.到现在为止还挺好.然后我有一些重载流接口的类:
class KxSymbol
{
operator u32() const;
friend KxStream& operator<<( KxStream& os, KxSymbol sym );
};
Run Code Online (Sandbox Code Playgroud)
请注意,此类将运算符强制转换为内置类型.现在,当我尝试将其中一个类流式传输到实现流式接口的类之一时,我收到一个错误:
KxCbuf buf;
KxSymbol sym;
buf << sym; // error!
Run Code Online (Sandbox Code Playgroud)
编译器对使用哪些函数感到困惑.Gcc编译得很好,但是说有很多方法可以做到这一点.MSVC没有编译说有多个重载:
src/variable.cpp(524) : error C2666: 'KxCbuf::operator <<' : 15 overloads have similar conversions
Run Code Online (Sandbox Code Playgroud)
我知道发生了什么,而不是如何令人满意地解决它.所以编译器可以转换KxCbuf - > KxStream,然后调用friend函数,这是正确的事情.或者它可以转换KxSymbol - > u32,然后在KxCbuf中调用u32 <<运算符,继承自KxStream.
我可以解决两个(坏)方式.
我可以从流明的东西开始明确:
buf << "" << sym;
Run Code Online (Sandbox Code Playgroud)
这样,""返回KxStream的第一个流操作符的返回值,一切都很好.或者我可以为实现类实现冗余流操作符.例如,我可以将以下内容添加到KxSymbol:
friend KxStream& operator<<( KxCbuf& os, KxSymbol sym );
Run Code Online (Sandbox Code Playgroud)
第一个答案总是有效 - 但肯定是丑陋的.第二个答案也很丑陋,因为我必须创建冗余流操作符,并不总是这样,因为KxStream实现在我需要定义新流操作符的地方并不总是可见.
理想情况下,我希望KxStream接口的实现与KxStream对象一样工作,并避免导致模糊转换的隐式转换.
我该如何解决这个问题?
(ps.我需要为我的库创建自己的流式操作符,用于自定义序列化方案.我不能使用具有自己的序列化类的boost或类似的第三方库)
@Edit:有几个很好的答案与控制编译器使用隐式转换有关,比如转换为KxSymbol - > u32,遗憾的是隐式转换对代码很重要.例如,KxSymbol是一个在表中存储字符串并将它们作为数字返回的类,以便我可以将字符串作为数字进行比较.例如,如果两个符号不相等,则字符串不相同.我还将符号存储为某些数据结构中的数字.
有没有办法从另一方面解决这个问题,以某种方式使编译器理解KxStream的实现应该优先于其他隐式转换强制转换为KxStream对象?
例如,如果我以某种方式强制编译器必须首先将KxCbuf强制转换为KxStream,然后才使用运算符<<作为内置类型.这将使它总是更喜欢重载运算符<< s over KxStream. - 重载需要一次转换,而KxStream则需要两次.