c ++即使定义了运算符也没有运算符匹配
c++ no operator matches even when operator is defined
我正尝试在 C++ 中实现自定义引用。我要实现的是有引用,不需要在创建的时候设置。看起来像这样
template<typename T>
class myreference
{
public:
myreference() : data(), isset(false) { }
explicit myreference(const T& _data) : data(&_data), isset(true) { }
myreference<T>& operator=(T& t)
{
if (!isset)
{
isset= true;
data = &t;
}
else
*data = t;
return *this;
}
operator T() const { return *data; }
operator T&() { return *data; }
private:
T* data;
bool isset;
};
它工作正常。我可以做到这一点,除了最后一句话。
myreference<int> myref;
int data = 7, test = 3;
myref = data; // reference is set
myref = test; // data is now 3
int& i = myref;
i = 4; // data is now 4
cout << myref; // implicit int conversion
myref = 42; // error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int'
完全错误
error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
1> d:\...\main.cpp(33): could be 'myreference<int> &myreference<int>::operator =(const myreference<int> &)'
1> d:\...\main.cpp(16): or 'myreference<int> &myreference<int>::operator =(T &)'
1> with
1> [
1> T=int
1> ]
1> while trying to match the argument list 'myreference<int>, int'
我在网上搜索并发现了类似的错误(使用 不同的 运算符),结果是将运算符放在它的类之外,但这对于 operator=
出于某些(我相信很好的)原因。我的问题是,编译器在抱怨什么?参数列表是 myreference<int>, int
并且我为 T
s 定义了运算符,在这种情况下,它是 int
.
由于赋值运算符需要变量(在本例中为整数),因此不允许将某个值 (42) 传递给它。
所以使用像
这样的整数
int x=42;
myref=x;
编码愉快。
myreference<T>& operator=(T& t)
myref = 42;
非常量引用不能绑定到临时引用。您可以将其更改为通过 const 引用获取参数。
myreference<T>& operator=(const T& t)
此外,请更改您的代码以使其正常工作。
data = &t; <<< Replace this
data = const_cast<T*>(&t); <<< with this.
您实例化了一个 myreference<int>
类型的对象
myreference<int> myref;
所以赋值运算符专门针对参数类型int &
。但是,您正在尝试分配一个可能绑定到常量引用的临时对象。所以赋值运算符必须专门用于参数类型 const int &
.
因此您需要定义另一个 myreference<const int>
类型的对象,代码至少会被编译。例如
myreference<const int> myref1;
myref1 = 42;
然而在任何情况下,代码都会有未定义的行为,因为执行此赋值语句后临时对象将被删除,数据成员数据将具有无效值。
通常这样的 claases 禁止使用临时对象来避免未定义的行为。
你的问题比编译器错误更大。编译器错误告诉你你有一个基本的设计错误。
您的引用 =
既充当引用重新绑定器(更改空引用附加到的对象)又充当赋值(更改附加对象的值)。这些是根本不同的操作。
一个需要一个可以稍后修改(重新绑定)的长期值,另一个需要一个可以从中读取的值(赋值)。
然而,对于一个函数,传递的参数必须是其中之一——而且这些类型不匹配。可读值是 T const&
。可绑定值是 T&
.
如果您将类型更改为 T const&
,则重新绑定 data = &t
会失败,这是应该的。如果你传递一个临时的,比如 42
,到你的 =
,一个重新绑定附加到它,并在调用行的末尾变得无效。同样,如果您将 int const foo = 3;
分配给它。
您可以 'fix' 使用 const_cast
,但这只会抛出检查 window 的类型:它隐藏了未定义的行为,而不是给您诊断。
另一方面,T&
参数不能绑定到 42
临时值,也不能绑定到常量 const int foo = 3
。这在重新绑定的情况下很好,但使赋值有点无用。
如果您有两个操作,=(T const &)
和 .rebind(T&)
,您的问题就会消失。作为副作用, =
未设置时是未定义的行为。不过以前基本都是这样。
此时您的参考文献最好称为 'pointer'。
我正尝试在 C++ 中实现自定义引用。我要实现的是有引用,不需要在创建的时候设置。看起来像这样
template<typename T>
class myreference
{
public:
myreference() : data(), isset(false) { }
explicit myreference(const T& _data) : data(&_data), isset(true) { }
myreference<T>& operator=(T& t)
{
if (!isset)
{
isset= true;
data = &t;
}
else
*data = t;
return *this;
}
operator T() const { return *data; }
operator T&() { return *data; }
private:
T* data;
bool isset;
};
它工作正常。我可以做到这一点,除了最后一句话。
myreference<int> myref;
int data = 7, test = 3;
myref = data; // reference is set
myref = test; // data is now 3
int& i = myref;
i = 4; // data is now 4
cout << myref; // implicit int conversion
myref = 42; // error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int'
完全错误
error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
1> d:\...\main.cpp(33): could be 'myreference<int> &myreference<int>::operator =(const myreference<int> &)'
1> d:\...\main.cpp(16): or 'myreference<int> &myreference<int>::operator =(T &)'
1> with
1> [
1> T=int
1> ]
1> while trying to match the argument list 'myreference<int>, int'
我在网上搜索并发现了类似的错误(使用 不同的 运算符),结果是将运算符放在它的类之外,但这对于 operator=
出于某些(我相信很好的)原因。我的问题是,编译器在抱怨什么?参数列表是 myreference<int>, int
并且我为 T
s 定义了运算符,在这种情况下,它是 int
.
由于赋值运算符需要变量(在本例中为整数),因此不允许将某个值 (42) 传递给它。 所以使用像
这样的整数int x=42;
myref=x;
编码愉快。
myreference<T>& operator=(T& t)
myref = 42;
非常量引用不能绑定到临时引用。您可以将其更改为通过 const 引用获取参数。
myreference<T>& operator=(const T& t)
此外,请更改您的代码以使其正常工作。
data = &t; <<< Replace this
data = const_cast<T*>(&t); <<< with this.
您实例化了一个 myreference<int>
myreference<int> myref;
所以赋值运算符专门针对参数类型int &
。但是,您正在尝试分配一个可能绑定到常量引用的临时对象。所以赋值运算符必须专门用于参数类型 const int &
.
因此您需要定义另一个 myreference<const int>
类型的对象,代码至少会被编译。例如
myreference<const int> myref1;
myref1 = 42;
然而在任何情况下,代码都会有未定义的行为,因为执行此赋值语句后临时对象将被删除,数据成员数据将具有无效值。
通常这样的 claases 禁止使用临时对象来避免未定义的行为。
你的问题比编译器错误更大。编译器错误告诉你你有一个基本的设计错误。
您的引用 =
既充当引用重新绑定器(更改空引用附加到的对象)又充当赋值(更改附加对象的值)。这些是根本不同的操作。
一个需要一个可以稍后修改(重新绑定)的长期值,另一个需要一个可以从中读取的值(赋值)。
然而,对于一个函数,传递的参数必须是其中之一——而且这些类型不匹配。可读值是 T const&
。可绑定值是 T&
.
如果您将类型更改为 T const&
,则重新绑定 data = &t
会失败,这是应该的。如果你传递一个临时的,比如 42
,到你的 =
,一个重新绑定附加到它,并在调用行的末尾变得无效。同样,如果您将 int const foo = 3;
分配给它。
您可以 'fix' 使用 const_cast
,但这只会抛出检查 window 的类型:它隐藏了未定义的行为,而不是给您诊断。
另一方面,T&
参数不能绑定到 42
临时值,也不能绑定到常量 const int foo = 3
。这在重新绑定的情况下很好,但使赋值有点无用。
如果您有两个操作,=(T const &)
和 .rebind(T&)
,您的问题就会消失。作为副作用, =
未设置时是未定义的行为。不过以前基本都是这样。
此时您的参考文献最好称为 'pointer'。