C++ 重载=C++;更多结构

C++ 重载=C++;更多结构,c++,C++,我正在为people register编写程序,但重载运算符= 我有classCRegister、structPerson和Place struct Places{ char date[11]; char * street; char * city; Places & operator = (const Places & other){ delete [] street; delete [] city;

我正在为people register编写程序,但重载运算符=

我有class
CRegister
、struct
Person
Place

struct Places{
    char date[11];
    char * street;
    char * city;

Places & operator = (const Places & other){
        delete [] street;
        delete [] city;

        strncpy (date, other.date, 11);

        int len;
        len = strlen(other.street);
        this->street = new char[len];
        strncpy ( this->street, other.street, len );

        len = strlen(other.city);
        this->city = new char[len];
        strncpy ( this->city, other.city, len );

        return *this;
    }
}


struct Person{
    char id[12];
    char * name;
    char * surname;
    Places ** oldPlaces;

    int placesCount;
    int placesSize;
};

Person & Person::operator =(const Person& other){
    for (int i = 0; i < this->placesSize; i++){
         delete this->oldPlaces[i];
    }
    delete [] this->oldPlaces;
    delete [] name;
    delete [] surname;


    placesCount = other.placesCount;
    placesSize = other.placesSize;

    oldPlaces = new Places*[other.placesSize];

    strncpy (id, other.id, 11);

        int len;

        len = strlen(other.name);
        this->name = new char[len];
        strncpy ( this->name, other.name, len );

        len = strlen(other.surname);
        this->surname = new char[len];
        strncpy ( this->surname, other.surname, len );

    for (int i = 0; i < placesCount; i++){
        oldPlaces[i] = other.oldPlaces[i];
    }

    return *this;
}



class CRegister     
 {
   private:
    Person **persons;
    int personCount;
    int personSize;
 };

 CRegister& CRegister::operator =(const CRegister& other){
    for (int i = 0; i < this->personSize; i++){
        delete this->persons[i];
    }
    delete [] this->persons;

    personCount = other.personCount;
    personSize = other.personSize;

    persons = new Person*[other.personSize];

    for (int i = 0; i < personCount; i++){
        persons[i] = other.persons[i];
    }


    return *this; 
 }
struct-Places{
字符日期[11];
查*街;
查尔*城市;
位置和运算符=(常量位置和其他){
删除[]街;
删除[]城市;
strncpy(日期,其他日期,11);
内伦;
len=斯特伦(其他街道);
此->街道=新字符[len];
strncpy(本->街,其他街,len);
len=斯特伦(其他城市);
这个->城市=新字符[len];
strncpy(this->city,other.city,len);
归还*这个;
}
}
结构人{
字符id[12];
字符*名称;
查*姓;
地点**旧址;
原地踏步;
内置化;
};
Person和Person::operator=(const Person和other){
对于(inti=0;iplacesSize;i++){
删除此->旧位置[i];
}
删除[]此->旧位置;
删除[]名称;
删除[]姓;
PlaceScont=其他。PlaceScont;
placesSize=other.placesSize;
oldPlaces=新地点*[other.placesSize];
strncpy(id,other.id,11);
内伦;
len=strlen(其他名称);
此->名称=新字符[len];
strncpy(this->name,other.name,len);
len=斯特伦(其他姓氏);
这个->姓氏=新字符[len];
strncpy(此->姓氏,其他。姓氏,len);
for(int i=0;ipersonSize;i++){
删除此->人员[i];
}
删除[]本->人;
personCount=other.personCount;
personSize=other.personSize;
人员=新人员*[其他.人员大小];
for(int i=0;i

但是,代码已编译,但Netbeans显示运行失败。为什么?

您没有遵循。这可能是一个原因,如果不是唯一的原因的话

另一方面

  • 为什么不直接使用
    std::string
  • 为什么不使用

这不会保留字符串的长度。以后的代码怎么知道这个城市有多长时间?

因为你基本上使用C(包装在类中):你已经 C代码中最常见的错误可能是什么<代码>strlen
返回字符串中的字符数,不计算 最后的
“\0”
strcpy
复制最后的
'\0'
,所以再复制一个 字符,如果使用
strncpy
(正如您所做的,您 不应该),那么您将得到一个不是
“\0”
已终止。因此,使用strcpy,您将超出 缓冲区,任何试图读取字符串的人都可以使用
strncpy
将溢出缓冲区的结尾(因为它们将继续 直到出现一个
'\0'

规则是比strlen多分配一个字符 返回:

(虽然不是标准的C,但许多系统都有
strdup
功能 当然,使用
malloc
,所以 使用
free
进行释放,而不是
delete

除此之外,我将重复我之前说过的话:您的代码将 如果出现以下情况之一,请使对象保持不一致状态: 分配失败。总是做任何可能失败的事情 在修改类中的任何内容之前。交换成语是 对于
运算符=
,经典,但在其他情况下,可以使用本地 指针:

char* newName = NULL;
char* newSurname = NULL;
Places* newPlaces = NULL;

try {
    newName = strdup( other.name);
    newSurname = strdup( other.surname );
    newPlaces = deapCopyPlaces( other.places );
} catch ( ... ) {
    deepDelete( newPlaces );
    delete [] newName;
    delete [] newSurname;
}
//  And only now...
deepDelete( places );
delete [] name;
delete [] surname;
name = newName;
surname = newSurname;
places = newPlaces;
但是swap习惯用法更受欢迎,因为它避免了
复制所有错误处理代码。

并非所有运算符都可以重载。=这是其中之一these@CapelliC嗯,什么?!?当然,
operator=
可以重载。使用
std::string
。2.利润。@capelical:当然,你可以重载op=,在三种情况下,你甚至应该这样做。永远不要只说“不起作用”。告诉它你想要它做什么,以及会发生什么!所以我必须写len+1,即“\0”的最后一个位置?这是一种方法。不过,使用
std::string
会更有意义。这是家庭作业,我们不能使用string。不幸的是,您能创建自己的string类吗?(我希望如此,因为强迫人们以非常糟糕的方式做事会让他们养成坏习惯。)这与他的原始代码存在同样的问题
strlen
不计算最后的
'\0'
,但必须将其复制到目标字符串。
size_t len = strlen( other.name ) + 1;
name = new char[ len ];
strcpy( name, other.name );
char* newName = NULL;
char* newSurname = NULL;
Places* newPlaces = NULL;

try {
    newName = strdup( other.name);
    newSurname = strdup( other.surname );
    newPlaces = deapCopyPlaces( other.places );
} catch ( ... ) {
    deepDelete( newPlaces );
    delete [] newName;
    delete [] newSurname;
}
//  And only now...
deepDelete( places );
delete [] name;
delete [] surname;
name = newName;
surname = newSurname;
places = newPlaces;