Проблема с динамическим выделением памяти при использовании конструкторов для класса

#c #oop #dynamic-memory-allocation

#c #ооп #динамическое выделение памяти

Вопрос:

я изучаю концепцию объектно-ориентированного программирования

Начал с динамического выделения памяти и нашел проблему в этом коде . Я не могу найти проблему в этом коде, на мой взгляд, все хорошо

 #include <iostream>

using namespace std;
class Team
{
    private:
    char *name;
    char stadium[20];
    char city[20];
    public:
    Team(const char *i=" ",const char *stadium=" ",const char *city=" ")
    {
        name=new char [strlen(i)];
        strcpy(name,i);
        strcpy(this->stadium,stadium);
        strcpy(this->city,city);
    }
  const char *getName() {
  return name;
  }
  const char *getCity() {
  return city;
  }
  const char *getStadium() {
  return stadium;
  }
  void setName(char *name) {
  strcpy(this->name, name);
  }
  ~Team() {
      delite [] name;
  }
};

};
int main()
{
  Team *e1 = new Team("Real Madrid", "Madrid", "Santiago Bernabeu");
  Team *e2 = new Team(*e1);
  cout << e1->getName();
  cout << "-";
  cout << e2->getName();
  e1->setName("Barselona");
  cout << e1->getName();
  cout << "-";
  cout << e2->getName();
  delete e1;
  delete e2;
   
   return 0;
}
  

Я пытался решить эту проблему более 3 часов… и ничего не нашел, я знаю, что это может быть не тот способ, которым мне нужно искать решение. Но я устал пытаться это исправить.

Некоторые из ошибок, которые я получаю

 main.cpp: In constructor ‘Team::Team(const char*, const char*, const char*)’:
main.cpp:13:24: error: ‘strlen’ was not declared in this scope
         name=new char [strlen(*i)];
                        ^~~~~~
main.cpp:13:24: note: suggested alternative: ‘mbrlen’
         name=new char [strlen(*i)];
                        ^~~~~~
                        mbrlen
main.cpp:14:9: error: ‘strcpy’ was not declared in this scope
         strcpy(name,i);
         ^~~~~~
main.cpp:14:9: note: suggested alternative: ‘strtoq’
         strcpy(name,i);
         ^~~~~~
         strtoq
  

Я попробовал этот код

 #include<iostream>
#include<cstring>
using namespace std;
class Team {
private:
  char *name;
  char city[20];
  char stadion[30];
public:
  Team(char *name = "", char *city = "", char *stadion = "") {
  this->name = new char[20];
  strcpy(this->name, name);
  strcpy(this->city, city);
  strcpy(this->stadion, stadion);
  }
  Team(const Team amp;e) {
  strcpy(name, e.name);
  strcpy(city, e.city);
  strcpy(stadion, e.stadion);
  }
  const char *getName() {
  return name;
  }
  const char *getCity() {
  return city;
  }
  const char *getStadion() {
  return stadion;
  }
  void setName(char *name) {
  strcpy(this->name, name);
  }
  ~Team() {
     // delite [] name;
  }
};
int main() {
  Team *e1 = new Team("Real Madrid", "Madrid", "Santiago Bernabeu");
  Team *e2 = new Team(*e1);
  cout << e1->getName();
  cout << "-";
  cout << e2->getName();
  e1->setName("Barselona");
  cout << e1->getName();
  cout << "-";
  cout << e2->getName();
  delete e1;
  delete e2;
  return 0;
}
  

И получаем эту ошибку

 main.cpp:44:26: warning: ISO C   forbids converting a string constant to ‘char*’ [-Wwrite-strings]                                                   
Segmentation fault (core dumped)
  

Комментарии:

1. Не могли бы вы добавить сообщение об ошибке и некоторую информацию о том, что вы пробовали?

2. я отредактирую сообщение сейчас, не беспокойтесь 🙂

3. Что не так с std::string ? И если вы настаиваете на ручном выделении памяти для строк, имейте в виду, что strlen(i) (не strlen(*i) ) не включает нулевой ограничитель. Также delite [] name; недопустим C

4. исправлено, но все еще не работает, может проблема в том, что я создаю объект в динамической памяти с динамическими выделенными параметрами?

Ответ №1:

Я исправил некоторые опечатки в вашем коде, модифицировал конструктор копирования class Team , и он отлично работает на моем компьютере.

 class Team
{
private:
    char* name;
    char stadium[20];
    char city[20];
public:
    Team(const char* i = " ", const char* stadium = " ", const char* city = " ")
    {
        name = new char[strlen(i)   1];  //  1 for null-terminate
        strcpy(name, i);
        strcpy(this->stadium, stadium);
        strcpy(this->city, city);
    }
    // allocating memory for Team::name needed, but I delegated it to above constructor.
    Team(const Teamamp; e) :Team(e.name, e.stadium, e.city) {
        // empty
    }
    const char* getName() {
        return name;
    }
    const char* getCity() {
        return city;
    }
    const char* getStadium() {
        return stadium;
    }
    void setName(const char* name) {  // must be const char*. Not char*!!
        strcpy(this->name, name);
    }
    ~Team() noexcept {
        if(name)        
            delete[] name;   // delete[] name, NOT delite
    }
};
  

Вот более предпочтительный способ написания классов C .
Как уже говорилось в некоторых комментариях, предпочитаю использовать std::string to char* . Я знаю, что, возможно, трудно привыкнуть к классам C , но, поверьте мне, std::string это намного лучше, чем char* . С std::string вам не нужно самостоятельно выделять память, и вам не требуется писать дополнительный конструктор копирования и деструктор.

 #include <string>

using std::string;

class Team
{
public:
    Team(void) = default;
    explicit Team(const stringamp; name, const stringamp; stadium, const stringamp; city)
        :name_(name), stadium_(stadium), city_(city) {}

    void setName(const stringamp; new_name) { name_ = new_name; }
    string getName(void) const { return name_; }
    string getCity(void) const { return city_; }
    string getStadium(void) const { return stadium_; }
private:
    string name_;
    string stadium_;
    string city_;
};
  

Комментарии:

1. я пробовал это, но все еще не работает… code error: ‘strlen’ was not declared in this scope name = new char[strlen(i) 1]; // 1 for null-terminate main.cpp:15:9: error: ‘strcpy’ was not declared in this scope strcpy(name, i);

2. @World Вы должны включить <cstring> в C , чтобы использовать strcpy() и strlen() .

3. да .. это была проблема так… Не обращайте внимания на тебя, парень с большими мозгами: D <3

4. Педантичный момент — при копировании строк в буферы символов действительно следует использовать strncpy или strcpy_s . (стадион и город). Также, если у вас есть открытые указатели, должен быть конструктор по умолчанию для его инициализации nullptr или объявления deleted .

5. Я бы также предложил, возможно, использовать ссылки rvalue для конструктора, чтобы вы могли создать экземпляр с char-const* строками.

Ответ №2:

Добавьте #include <cstring> в свой основной файл: C

 #include <iostream>
using namespace std;
#include<cstring>  // Add this in your code
  

В вашем основном файле:

 int main() {
   ...
}