不称为默认构造函数和复制构造函数(可能还有其他逻辑错误) [英] Not called default constructor and copy constructor (and maybe other logical errors)

查看:88
本文介绍了不称为默认构造函数和复制构造函数(可能还有其他逻辑错误)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#include <iostream>
#define MAX 10

using namespace std;

class Person
{


  private:
    char *name;
    char *surname;
    double age;

  public:

    Person(): name(NULL), surname(NULL), age(0.0L)
    {
        cout << "default costructor activated\n";
    }
    Person(char *n, char *sn, double ag): name(n), surname(sn), age(ag)
    {
        cout << "normal costructor activated\n";
    }
    Person(const Person &p)
    {

        if (name != NULL)
        {
            delete name;
            name = NULL;
        }

        if (surname != NULL)
        {
            delete surname;
            surname = NULL;
        }



        name = new char[strlen(p.name) + 1];
        strcpy(name, p.name);

        surname = new char[strlen(p.surname) + 1];
        strcpy(surname, p.surname);

        age = p.age;

        cout << "copy costructor activated\n";
    }


    ~Person()
    {

        if (name != NULL)
        {
            delete name;
            name = NULL;
        }

        if (surname != NULL)
        {
            delete surname;
            surname = NULL;
        }

        age = 0.0L;
        cout << "destructor costructor activated\n";
    }


    void display(void);

    void setName(char*);
    void setSurname(char*);
    void setAge(double);

    Person *operator = (Person*);

    friend int calculateBirthYear(Person &);
};


Person *Person::operator = (Person *p) //implementation of assignment operator
{

  if (name != NULL)
  {
    delete name;
    name = NULL;
  }

  if (surname != NULL)
  {
    delete surname;
    surname = NULL;
  }



  name = new char[strlen(p->name) + 1];
  strcpy(name, p->name);

  surname = new char[strlen(p->surname) + 1];
  strcpy(surname, p->surname);

  age = p->age;
  cout << "Assigment operator activated\n";

  return this;


}

void Person::setName(char *onoma) //onoma mean name
{
  if (name != NULL)
  {
    delete name;
    name = NULL;
  }

  name = new char[strlen(onoma) + 1];
  strcpy(name, onoma);


}


void Person::setSurname(char *eponumo) //eponumo mean surname
{

  if (surname != NULL)
  {
    delete surname;
    surname = NULL;
  }

  name = new char[strlen(eponumo) + 1];
  strcpy(surname, eponumo);



}


void Person::setAge(double ilikia) //ilikia mean age
{

  age = ilikia;



}


void Person::display()
{

  cout << "name: " << name << "\n";
  cout << "Surname: " << surname << "\n";
  cout << "Age: " << age << "\n";

}



int calculateBirthYear(Person &);

int main(void)
{


  char *onoma = NULL,  *eponumo = NULL;
  double age = 0.0L;
  int BirthYear = 0;
  onoma = new char[50];
  eponumo = new char[50];
  short data = 2, raise = 2;

  Person **p = new Person *[MAX];
  for (int c = 0; c < 10; c++)
    p[c] = NULL;       


  cout << "Enter number of data (max 10, by default 2): ";
  cin >> raise;
  system("cls");

  if (raise > 2 && raise < 11)
    data = raise;

  cout << "\t\t\t Insert Data of " << data << " People \n\n\n";

  for (int i = 0; i < data; i++)
  {

    cout << "\nName: ";
    cin >> onoma;

    cout << "Surname: ";
    cin >> eponumo;

    cout << "Age: ";
    cin >> age;
    cout << "\n\n";

    p[i] = new Person(onoma, eponumo, age);
  }

  system("cls");
  cout << "\t\t\t   People Data\n\n\n";
  for (int i = 0; i < data; i++)
  {

    p[i]->display();
    BirthYear = calculateBirthYear(*p[i]);
    cout << "BirthYear: " << BirthYear;
    cout << "\n\n";
  }


  delete [] p;
  delete [] onoma;
  delete [] eponumo;

  cout << "\n\n\n";
  system("PAUSE");
  return 0;
}


int calculateBirthYear(Person &p)
{

  int currentYear = 2012;
  int birthYear = currentYear - static_cast < int > (p.age);
  return birthYear;


}

推荐答案

是的。默认构造函数未被调用,因为您没有编写任何代码来调用它。

执行此行
Yes. default constructor is not called because you havent written any code to call it.
By executing this line
p[i] = new Person(onoma, eponumo, age);

它找到匹配的构造函数,它具有已定义的参数并被调用,而不是默认或参数无构造函数。



是副本没有调用构造函数,因为你没有编写任何代码来调用它。

复制构造函数调用后调用三次

1.实例化一个对象并初始化它与来自另一个对象的值(如上例所示)。

2.按值传递对象时。

3.当一个对象从函数返回时价值。


ie

it finds the matching constructor which has parameters defined and gets called and not the default or parameter none constructor.

Yes copy constructor is not called because you havent written any code to call it.
copy constructor gets call called in following three occasions
1.When instantiating one object and initializing it with values from another object (as in the example above).
2.When passing an object by value.
3.When an object is returned from a function by value.

ie

main
{
 Person p(on0ma,epunumo,age);
 Person p1 = p; // Copy Constructor gets called
}



了解有关Copy Constructor的更多信息@ CPlusPlus论坛 [ ^ ]


只有在使用参数创建对象时才调用默认构造函数较少的构造函数...



我发现您的代码中有一些错误或可能的改进:



Default constructor is called only when you create an object using parameter-less constructor...

I have found a few mistakes or possible improvements in your code:

#define MAX 10



最好使用常量代替。应尽可能避免宏,因为他们不尊重范围。




It would be preferable to uses a constant instead. Macros should be avoided whenever possible as they don''t respect scope.

Person(const Person &p)
{
    if (name != NULL)
    {
        delete name;
        name = NULL;
    }

    if (surname != NULL)
    {
        delete surname;
        surname = NULL;
    }
    // ...



这段代码完全无用,实际上是错误的。由于复制构造函数是在未初始化的新对象上调用的,因此无法删除姓名或姓氏。


This code is totally useless and in fact wrong. Since copy constructor is called on a new object which is uninitialized, you cannot delete name or surname.

~Person()
{
    if (name != NULL)
    {
        delete name;
        name = NULL;
    }

    if (surname != NULL)
    {
        delete surname;
        surname = NULL;
    }
    age = 0.0L;

    cout << "destructor costructor activated\n";
}



以前的大多数代码基本没用。当一个对象被破坏时,它不能在以后合法使用,所以清除所有变量毫无意义。你可以这样做:


Most of previous code is essentially useless. When an object is destroyed, it cannot be legally used afterward so it pointless to clear all variables. You could simply do that instead:

~Person()
{
    delete[] name;
    delete[] surname;

    cout << "destructor costructor activated\n";
}







void setName(char*);
void setSurname(char*);

Person *operator = (Person*);

friend int calculateBirthYear(Person &);



在上一个函数中你应该添加一些const修饰符,你应该使用 = operator 。它应该是人和& operator =(const Person&);

另外calculateBirthYear不应该是朋友。你应该有一个公共成员来获得年龄。顺便说一下,该功能无法正确实现,因为您需要知道当前日期和生日以正确确定年龄。


In previous function you should add some const modifiers and also, you should use standard prototype for =operator. It should be Person& operator=(const Person &);
Also calculateBirthYear should not be friend. You should have a public member to get the age. By the way, the function cannot be implemented correctly because you need to know the current date and the birthday to properly determine the age.

Person *Person::operator = (Person *p) //implementation of assignment operator
{
    // ...
}



如果无法分配内存,那么您的实现不是异常安全的......其他一些函数也是如此。通常,您希望在删除旧内容之前执行新分配,这样如果它不起作用,您的对象仍将处于稳定状态。使用RAII习语是一个很好的模式。


Your implementation is not exception safe if memory cannot be allocated... So are some other functions. Generally, you want to do new allocation before deleting old stuff so that if it does not works, your object will still be in a stable state. Using RAII idiom is a good pattern to follows.

name = new char[strlen(onoma) + 1];
strcpy(name, onoma);



此代码重复。为什么不为此目的添加静态成员函数?


This code is repetitive. Why not add a static member function for that purpose?

int main(void)
{
  //...
}



main 函数有一些内存泄漏( Person数组中的不会被删除。)



此外,还有一堆硬编码常量。例如,如果修改 MAX ,则不会调整消息和范围检查。



作为旁注,在你的程序中使用 std :: vector std :: string 会更好,以避免大量的显式内存管理,并且具有异常安全的代码。


The main function has some memory leaks (Person in the array are not deleted).

Also, there are still a bunch of hard-coded constants. For example if MAX is modified then neither the message nor the range check are adjusted.

As a side note, it would be better to use std::vector and std::string in your program to avoid a lot of explicit memory management and have code that it is exception-safe.


使用

std :: string name,surname;

your代码将非常简单。
use
std::string name,surname;
your code will be very simple.


这篇关于不称为默认构造函数和复制构造函数(可能还有其他逻辑错误)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆