关于运算符重载的问题

时间:2022-10-19 17:34:12
大家好,我编了一个关于运算符重载方面的程序,其功能是将一个类对象赋值给另外一个类对象。当我想将用类的成员函数实现的方法改变成普通函数实现时出现一对莫名其妙的错误,请各位大牛们给我指教一下,谢谢!

//这是用类的成员函数实现的方法:

//用普通函数实现:

#include <iostream>
#include <cstring>
using std::cout;
using std::endl;

class CMessage
{
public:
char* pmessage;                   

public:
// Function to display a message
void ShowIt() const
{
cout << endl << pmessage;
}

void Reset()
{
char* temp = pmessage;
while(*temp)
*(temp++) = '*';
}

CMessage(const char* text = "Default message")
{
pmessage = new char[ strlen(text) +1 ]; 
strcpy(pmessage, text);              
}

~CMessage()
{
cout << "Destructor called."    
<< endl;
delete[] pmessage;            
}
};

//运算符重载
int operator = (CMessage& msg1, const CMessage& msg2) 
{

delete [] msg1.pmessage;
msg1.pmessage = new char[strlen(msg2.pmessage)+1];
strcpy(msg1.pmessage, msg2.pmessage);

return 0;
}


int main()
{
CMessage motto1("The devil takes care of his own");
CMessage motto2;

cout << "motto2 contains - ";
motto2.ShowIt();
cout << endl;

motto2 = motto1;                      

cout << "motto2 contains - ";
motto2.ShowIt();
cout << endl;

motto1.Reset();                   

cout << "motto1 now contains - ";
motto1.ShowIt();
cout << endl;

cout << "motto2 still contains - ";
motto2.ShowIt();
cout << endl;

return 0;
}

错误:
1 warning C4996: 'strcpy' was declared deprecated
2 error C2801: 'operator =' must be a non-static member

请问这该怎么解决,还有这个用友元函数怎么实现??

12 个解决方案

#1


赋值操作符函数必须以成员函数形式重载。这也没法用友元函数实现。

#2



Error Message 
'operator operator' must be a non-static member


The following operators can be overloaded only as nonstatic members:

Assignment =

Class member access ->

Subscripting []

Function call ()

Possible C2801 causes:

Overloaded operator is not a class, structure, or union member.

Overloaded operator is declared static.

The following sample generates C2801:



#3


改operator=()成成员函数就没问题了.
motto2 = motto1;    
其实这个会调用 motto2.operator(motto1);但是不是成员函数 所以调用失败了.

#4


motto2.operator=(motto1);

#5


引用 1 楼 guuerpwustc 的回复:
赋值操作符函数必须以成员函数形式重载。这也没法用友元函数实现。

IT IS TRUE.

#6


1.赋值操作符是一元运算符,所以重载赋值操作符只能有一个参数
2.重载赋值操作符只能作为成员函数,所以不能通过友元来重载

修改如下:
#include <iostream> 
#include <cstring> 
using std::cout; 
using std::endl; 

class CMessage 

public: 
char* pmessage;                  

public:
    int operator = (const CMessage& msg2);

// Function to display a message 
void ShowIt() const 

cout << endl << pmessage; 


void Reset() 

char* temp = pmessage; 
while(*temp) 
*(temp++) = '*'; 


CMessage(const char* text = "Default message") 

pmessage = new char[ strlen(text) +1 ]; 
strcpy(pmessage, text);              


~CMessage() 

cout << "Destructor called."    
<< endl; 
delete[] pmessage;            

}; 

//运算符重载 
int CMessage::operator = (const CMessage& msg2) 
{

delete [] this->pmessage; 
this->pmessage = new char[strlen(msg2.pmessage)+1]; 
strcpy(this->pmessage, msg2.pmessage); 

return 0; 



int main() 

CMessage motto1("The devil takes care of his own"); 
CMessage motto2; 

cout << "motto2 contains - "; 
motto2.ShowIt(); 
cout << endl; 

motto2 = motto1;                      

cout << "motto2 contains - "; 
motto2.ShowIt(); 
cout << endl; 

motto1.Reset();                  

cout << "motto1 now contains - "; 
motto1.ShowIt(); 
cout << endl; 

cout << "motto2 still contains - "; 
motto2.ShowIt(); 
cout << endl; 

return 0; 

#7


对,=操作符必须是成员。

为什么必须是呢?试想一下如果可以写出下面这样子的代码:

class Int
{
  int m_i;
 public:
  Int(int i):m_i(i)
  {}

  void Set(int i)
  {
    m_i = i;
  }

  int Get()const
  {
    return m_i;
  }
};

Int operator=(const Int& lhs, const Int& rhs)
{
  return Int(rhs.Get() + lhs.Get());
}

//这句没问题
Int myInt = 3;

//而以下这个语句将会让编译器发疯:
int i = Int(2);


因为编译器可以找到整型变成Int类的方法(就是Int类的构造函数),却找不到Int类变成整型的方法。

#8


实际上int i = Int(2);可以重载int获得成立:

	Int::operator int()
{
return m_i;
}


而不是通过重载=成立。

刚才查看了一下C++ primer,说重载=必须是成员函数的原因是因为重载=作为成员会告诉编译器不用再自动生成operatpr=了。

#9


up~接分~!

#10


如何决定把一个操作符重载为类成员函数还是全局名字空间的成员?

①如果一个重载操作符是类成员,那么只有当与他一起使用的左操作数是该类的对象时,该操作符才会被调用。如果该操作符的左操作数必须是其他的类型,则操作符必须被重载为全局名字空间的成员。
②C++要求赋值=,下标[],调用(), 和成员指向-> 操作符必须被定义为类成员操作符。任何把这些操作符定义为名字空间成员的定义都会被标记为编译时刻错误。
③如果有一个操作数是类类型如string类的情形那么对于对称操作符比如等于操作符最好定义为全局名字空间成员。

#11


引用 7 楼 jackzhhuang 的回复:
对,=操作符必须是成员。

为什么必须是呢?试想一下如果可以写出下面这样子的代码:

C/C++ codeclassInt
{intm_i;public:
  Int(inti):m_i(i)
  {}voidSet(inti)
  {
    m_i=i;
  }intGet()const{returnm_i;
  }
};

Intoperator=(constInt&lhs,constInt&rhs)
{returnInt(rhs.Get()+lhs.Get());
}//这句没问题Int myInt=3;//而以下这个语句将会让编译器发疯:inti=Int(2);

因为编译器可以找到整型变成Int类的方法(就…


大师 说了 编译器 也不是神仙。

#12


1.C++规定,=运算符只能重载成成员重载
2。完整、完善的=运算符重载重载为
CMessage& CMessage::operator=(const CMessage& msg2){
if(this!=&msg2){//防止自身复制
delete [] pmessage; 
pmessage = new char[strlen(msg2.pmessage)+1]; 
strcpy(pmessage, msg2.pmessage); 
}
return *this; 

#1


赋值操作符函数必须以成员函数形式重载。这也没法用友元函数实现。

#2



Error Message 
'operator operator' must be a non-static member


The following operators can be overloaded only as nonstatic members:

Assignment =

Class member access ->

Subscripting []

Function call ()

Possible C2801 causes:

Overloaded operator is not a class, structure, or union member.

Overloaded operator is declared static.

The following sample generates C2801:



#3


改operator=()成成员函数就没问题了.
motto2 = motto1;    
其实这个会调用 motto2.operator(motto1);但是不是成员函数 所以调用失败了.

#4


motto2.operator=(motto1);

#5


引用 1 楼 guuerpwustc 的回复:
赋值操作符函数必须以成员函数形式重载。这也没法用友元函数实现。

IT IS TRUE.

#6


1.赋值操作符是一元运算符,所以重载赋值操作符只能有一个参数
2.重载赋值操作符只能作为成员函数,所以不能通过友元来重载

修改如下:
#include <iostream> 
#include <cstring> 
using std::cout; 
using std::endl; 

class CMessage 

public: 
char* pmessage;                  

public:
    int operator = (const CMessage& msg2);

// Function to display a message 
void ShowIt() const 

cout << endl << pmessage; 


void Reset() 

char* temp = pmessage; 
while(*temp) 
*(temp++) = '*'; 


CMessage(const char* text = "Default message") 

pmessage = new char[ strlen(text) +1 ]; 
strcpy(pmessage, text);              


~CMessage() 

cout << "Destructor called."    
<< endl; 
delete[] pmessage;            

}; 

//运算符重载 
int CMessage::operator = (const CMessage& msg2) 
{

delete [] this->pmessage; 
this->pmessage = new char[strlen(msg2.pmessage)+1]; 
strcpy(this->pmessage, msg2.pmessage); 

return 0; 



int main() 

CMessage motto1("The devil takes care of his own"); 
CMessage motto2; 

cout << "motto2 contains - "; 
motto2.ShowIt(); 
cout << endl; 

motto2 = motto1;                      

cout << "motto2 contains - "; 
motto2.ShowIt(); 
cout << endl; 

motto1.Reset();                  

cout << "motto1 now contains - "; 
motto1.ShowIt(); 
cout << endl; 

cout << "motto2 still contains - "; 
motto2.ShowIt(); 
cout << endl; 

return 0; 

#7


对,=操作符必须是成员。

为什么必须是呢?试想一下如果可以写出下面这样子的代码:

class Int
{
  int m_i;
 public:
  Int(int i):m_i(i)
  {}

  void Set(int i)
  {
    m_i = i;
  }

  int Get()const
  {
    return m_i;
  }
};

Int operator=(const Int& lhs, const Int& rhs)
{
  return Int(rhs.Get() + lhs.Get());
}

//这句没问题
Int myInt = 3;

//而以下这个语句将会让编译器发疯:
int i = Int(2);


因为编译器可以找到整型变成Int类的方法(就是Int类的构造函数),却找不到Int类变成整型的方法。

#8


实际上int i = Int(2);可以重载int获得成立:

	Int::operator int()
{
return m_i;
}


而不是通过重载=成立。

刚才查看了一下C++ primer,说重载=必须是成员函数的原因是因为重载=作为成员会告诉编译器不用再自动生成operatpr=了。

#9


up~接分~!

#10


如何决定把一个操作符重载为类成员函数还是全局名字空间的成员?

①如果一个重载操作符是类成员,那么只有当与他一起使用的左操作数是该类的对象时,该操作符才会被调用。如果该操作符的左操作数必须是其他的类型,则操作符必须被重载为全局名字空间的成员。
②C++要求赋值=,下标[],调用(), 和成员指向-> 操作符必须被定义为类成员操作符。任何把这些操作符定义为名字空间成员的定义都会被标记为编译时刻错误。
③如果有一个操作数是类类型如string类的情形那么对于对称操作符比如等于操作符最好定义为全局名字空间成员。

#11


引用 7 楼 jackzhhuang 的回复:
对,=操作符必须是成员。

为什么必须是呢?试想一下如果可以写出下面这样子的代码:

C/C++ codeclassInt
{intm_i;public:
  Int(inti):m_i(i)
  {}voidSet(inti)
  {
    m_i=i;
  }intGet()const{returnm_i;
  }
};

Intoperator=(constInt&lhs,constInt&rhs)
{returnInt(rhs.Get()+lhs.Get());
}//这句没问题Int myInt=3;//而以下这个语句将会让编译器发疯:inti=Int(2);

因为编译器可以找到整型变成Int类的方法(就…


大师 说了 编译器 也不是神仙。

#12


1.C++规定,=运算符只能重载成成员重载
2。完整、完善的=运算符重载重载为
CMessage& CMessage::operator=(const CMessage& msg2){
if(this!=&msg2){//防止自身复制
delete [] pmessage; 
pmessage = new char[strlen(msg2.pmessage)+1]; 
strcpy(pmessage, msg2.pmessage); 
}
return *this;