采取以下代码:
#include <string>
#include <iostream>
template <class T, class U>
class readonly
{
friend U;
private:
T data;
T operator=(const T& arg) {data = arg; return data;}
T operator+=(const T& arg) {data = data + arg; return data;}
T operator-=(const T& arg) {data = data - arg; return data;}
T operator*=(const T& arg) {data = data * arg; return data;}
T operator/=(const T& arg) {data = data / arg; return data;}
public:
operator const T&() const {return data;}
};
class myClass
{
private:
typedef readonly<int, myClass> RO_int;
typedef readonly<std::string, myClass> RO_string;
public:
RO_int x;
RO_string y;
void f()
{
x = 55;
y = "Howdy";
std::cout << x << "\n\n"; // compiles fine
std::cout << y << "\n\n"; // compile error
}
};
我正在使用这些模板类来确保某些公共(public)变量
x
和y
在类外部为“只读”,但可以在类本身内进行修改。除了我试图显示字符串类型的变量y的最后一行之外,这段代码中的所有内容都可以正常编译。我不明白为什么我可以显示x
而不显示y
。如果需要重载<<
运算符,为什么我必须对std::string
而不是对int
这样做呢? 最佳答案
首先,但不是您的问题,运算符(operator)应返回readonly&
或T&
而不是T
。不要那样破坏惯例。
现在是一个实际的答案。
这是因为operator<<
使用的string
是模板,并且模板功能在模式匹配时不考虑转换。接受<<
的int
不是模板,因此它确实考虑了转换。
我们通常可以通过创建一个不会转换的operator<<
来解决此问题:
只需添加
friend std::ostream& operator<<(std::ostream& os, readonly const& self)
{
return os<<self.data;
}
设置为
readonly
类型,然后一切正常。这可以通过ADL找到。我们可以通过使用模板中的第一个参数并检查
<<
是否有效以及第一个参数是否从std::ostream
派生,或者类似地使用第二个参数,来使SFINAE等产品更出色。关于c++ - 只读类变量(C++)和运算符重载,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44894802/