Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Перегрузка констуктора (http://forum.oszone.net/showthread.php?t=180695)

котвася 15-07-2010 22:11 1454149

Перегрузка констуктора
 
Как правильно перегружать конструктор? Помогите, не понятно.
Код:

#include <iostream>
class Date
{
public:
        Date(int, int);
        Date(int, int, int);
        void print() const;
        void setDate(int, int, int);
private:
        int day;
        int month;
        int year;
};

Date::Date(int dd, int mm, int yyyy)
{
        day = dd;
        month = mm;
        year = yyyy;
}

void Date::setDate(int dd, int mm, int yyyy)
{
        day = dd;
        month = mm;
        year = yyyy;
}
void Date::Date(int dd, int yyyy)
{
        day = dd;
        year = yyyy;
}

void Date::print() const
{
        std::cout << day << "/" << month << "/" << year << std::endl;
}
int main()
{
        setlocale(LC_ALL,".1251");
        Date d(2,2,2000);
        Date d2(1,1991);

        d.print();
        d2.print();

        system("pause");
        return 0;
}


котвася 15-07-2010 22:31 1454160

ха сам додумался
лишнем было
Код:

void Date::Date(int dd, int yyyy)
{
        day = dd;
        year = yyyy;
}

и как раз назрело еще два вопроса:
1) Как перегрузить print() что бы она понимала автоматически сколько ей печатать параметров?
2) Как перегрузить Date() c типом char?

котвася 16-07-2010 01:02 1454208

хо хо хо сам решил!
вот:
Код:


class Date
{
public:
        Date(int, char *, int);
        Date(int, int);
        Date(int, int, int);
       
        void print() const;
        void printChar() const;
        void setDate(int, int, int);
private:
        int day;
        int month;
        char *_month;
        int year;
};
Date::Date(int dd, char *mm, int yyyy)
{
        day = dd;
        _month = mm;
        year = yyyy;
}


El Scorpio 16-07-2010 05:54 1454258

Цитата:

Цитата котвася
Date::Date(int dd, char *mm, int yyyy)
{ day = dd; _month = mm; year = yyyy; }
»

Неправильно.
Представь,*что дальше в тексте программы будет команда на освобождение области памяти, на которую указывает mm. Тогда попытка обратиться к _month приведёт к ошибке.

И вообще, использовать char* нельзя. Для работы с текстом нужно объявлять объекты строковых контейнеров (string, AnsiString и т.д.)

котвася 16-07-2010 14:22 1454522

пример можно?

Glareone 16-07-2010 19:40 1454683

Цитата:

Цитата El Scorpio
И вообще, использовать char* нельзя. »

Цитата:

Цитата котвася
Date::Date(int dd, char *mm, int yyyy)
{ day = dd; _month = mm; year = yyyy; } »

В данном примере, действительно, так лучше не делать.Но вообще, использовать char* не запрещает никто. Просто за выделением памяти mm=new... delete[] mm; самому приходится следить.

pva 17-07-2010 09:49 1454878

ещё пара советов по оптимизации: исхожу из предположений
1) последовательность уточнения даты: год, месяц, день, час, минута, секунда, либо в обратном порядке. Т.е. нет смысла задавать дату днём и годом (без указания месяца).
2) обратный порядок нужен только для того, чтобы сокращённо задавать промежуток времени (например интервал 1 день 5 секунд). А его лучше задавать количеством секунд, а не датой. Поэтому обратный порядок тоже не нужен.
Код:

// Таким образом нужен один конструктор:
class Date {
public:
  Date(int year=0, int month=1, int day = 1, int hour=0, int min=0, int sec=0);
  ...
private:
  _hidden_init(); // не раскрывается inline
};

// т..к. по сути мы даём возможность заполнить структуру, то лучше вынести inline
// так мы разделим присвоение параметров (как бы inline) и дальнейшую обработку _hidden_init()
inline Date::Date(...)
{
  ...
  _hidden_init();
}

Если нужно иногда использовать время отдельно от даты, то можно сделать так:
Код:

// Таким образом нужен один конструктор:
class Time {
public: Time(int h, int m, int s);
};
class Date {
public: Date(int y, int m, int d);
};
class DateTime
{
public:
  DateTime(const Date&, const Time&);
  DateTime(const Date&);
  DateTime(const Time&);
};
// тогда путаницы не возникнет


Drongo 17-07-2010 13:53 1454961

pva, Он до этого дойдёт позже. :) В книге Дейтелов изучение классов начинается с самых простых примеров без проверки на ошибки и только чуть-чуть погодя будут этот класс Time улучшать, добавляя функции проверки, коррекции и т.д.

котвася 17-07-2010 22:52 1455232

pva, это я догоняю. Мне надо, например, перегрузить вот так: ДАТА(01 01 1900) и ДАТА( 1 января 1900). Не пойму пока как это сделать "правильно".
и вопрос:
если написать _hidden_init(); то конструктор перестает быть по умолчанию "встраиваемый" и будет "вызываться"?
и что бы он стал inline это надо явно указывать? я правильно понимаю?

котвася 17-07-2010 23:29 1455248

Нашел такое решение:
Код:

#include <iostream>
class Date
{
public:
        Date(int, char, int);
        Date(int, int, int);
       
        void print() const;
        void printChar() const;
        void setDate(int, int, int);
private:
        int day;
        int month;
        int year;
};
Date::Date(int dd, int mm, int yyyy)
{
        day = dd;
        month = mm;
        year = yyyy;
}
Date::Date(int dd, char mm, int yyyy)
{
        day = dd;
        month = mm;
        year = yyyy;
}

void Date::setDate(int dd, int mm, int yyyy)
{
        day = dd;
        month = mm;
        year = yyyy;
}

void Date::print() const
{
        if(month >= 0)
                std::cout << day << "/" <<  month << "/"  << year << std::endl;
        else
                std::cout << day << "/" << year << std::endl;
}
void Date::printChar() const
{
        std::cout << day << "/" <<  char(month) << "/"  << year << std::endl;
}

int main()
{
        setlocale(LC_ALL,".1251");
        char _month[]="январь";
        Date d(2,12,2000);
        std::cout << _month[0] << std::endl;
        Date d3(1, _month[0],1991);

        d.print();
        d3.printChar();

        system("pause");
        return 0;
}

только вот одна проблема:
в Date могу передать только одну букву названия месяца.
Так что думаю тут без * никак так как надо передавать массив. Или есть другой "правильный путь"?

Drongo 18-07-2010 10:13 1455381

Цитата:

Цитата котвася
Так что думаю тут без * никак так как надо передавать массив. Или есть другой "правильный путь"? »

Правильно. Используй символьный массив указателей. Я когда-то решал подобную задачу.

Date.h

Код:

// Определение класса Time
// Функции-члены определены в Date1.cpp

// Процессорные директивы, которые предотвращают
// многократное включение заголовочного файла
#ifndef DATE_H
#define DATE_H

class Date{
public:
    // конструктор
    Date(int = 1, int = 1, int = 1990);

    // печать дат в формате месяца/дня/года. 05.01.1997
    void print() const;

    // печать дат в формате число, срока названия месяца, год. 5 января 1997 год.
    void print_Day_StringMonth_Year() const;
    ~Date();

    // функцияи 'set' Установка и проверка вводимых параметров
    void setDate(int, int, int);  // установка дня, месяца, года
private:
    int day;      // День от 1 - 31
    int month;    // Месяц от 1 - 12
    int year;    // Год. Целое число

    // функция-утилита для проверки соответствия дня месяца и году
    int checkDay(int); // На всякий случай ;)))))
 };

#endif

Date.cpp

Код:

// определения функции-членов класса Date
#include <iostream.h>
using std::cout;
using std::endl;

#include "date.h"

// конструктор: поддержка соответствующего значения месяца;
// вызвать функцию-утилиту checkDay для поддержки соответствующего
// значения дня
Date::Date(int dy, int mn, int yr)
{
  setDate(dy, mn, yr); // Функция правильной установки дня, месяца, и года
}
// печать объекта Date в форме месяца/дня/года. 05.01.1997--------------------
void Date::print() const
{
  int NumbNullDay_and_Month, // Счётчик
      NumbNull_Day, // индекс для массива NumberDay_Month, для правильного отображения числа ДНЯ с нулём
      NumbNull_Month; // индекс для массива NumberDay_Month, для правильного отображения числа МЕСЯЦА с нулём

  static const char *NumberDay_Month [10] = {"", "01", "02", "03", "04", "05", "06", "07", "08", "09"};

  // Проверка дня, если в числе ДНЯ один разряд, вычислить соответствующий индекс массива NumberDay_Month...
  if(day < 10){
    for(NumbNullDay_and_Month = 0; NumbNullDay_and_Month < 11; NumbNullDay_and_Month++){
        if(NumbNullDay_and_Month == day)
          NumbNull_Day = NumbNullDay_and_Month;
    }
  }
  // Если в числе ДНЯ, больше одного разряда, то присвоить переменной NumbNull_Day, тоже число, что и было
  else if(day > 9)
    NumbNull_Day = day;

  // Проверка дня, если в числе МЕСЯЦА один разряд, вычислить соответствующий индекс массива NumberDay_Month...
  if(month < 10){
    for(NumbNullDay_and_Month = 0; NumbNullDay_and_Month < 11; NumbNullDay_and_Month++){
        if(NumbNullDay_and_Month == month)
          NumbNull_Month = NumbNullDay_and_Month;
    }
  }
  // Если в числе МЕСЯЦА, больше одного разряда, то присвоить переменной NumbNull_Day, тоже число, что и было
  else if(month > 9)
    NumbNull_Month = month;

  // Вывод вариантов
  if(day < 10 && month < 10) // Если в ДНЕ И в МЕСЯЦЕ число меньше десяти
    cout<<NumberDay_Month[NumbNull_Day]<<"."<<NumberDay_Month[NumbNull_Month]<<"."<<year<<endl;
  else if(day < 10 && month > 9) // Если в ДНЕ меньше деСяти, И в МЕСЯЦЕ больше деВяти
    cout<<NumberDay_Month[NumbNull_Day]<<"."<<NumbNull_Month<<"."<<year<<endl;
  else if(day > 9 && month < 10) // Если в ДНЕ больше деВяти, И в МЕСЯЦЕ больше деСяти
    cout<<NumbNull_Day<<"."<<NumberDay_Month[NumbNull_Month]<<"."<<year<<endl;
  else if(day > 9 && month > 9)  // Если в ДНЕ И в МЕСЯЦЕ число больше деСяти
    cout<<NumbNull_Day<<"."<<NumbNull_Month<<"."<<year<<endl;
}

// печать дат в формате число, строка названия месяца, год--------------------
void Date::print_Day_StringMonth_Year() const
{
  int i;
  static const char *Month [13] = {"", "Yanvaria", "Fevralia", "Marta", "Aprelia",
                                  "May", "Yuni", "Yuli", "Avgusta", "Sentyabria",
                                  "Ortyabria", "Noyabria", "Dekabria"};

      for(i = 0; i < 14; i++){
          if(month == i)
              cout<<day<<" "<<Month[i]<<" "<<year<<" God."<<endl;
        }
}
// функция-утилита для поддержки соответствующего
// значения дня в зависимости от месяца и года.
// является ли 2000-й год високосным?-----------------------------------------
int Date::checkDay(int testDay)
{
  static const int daysPerMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

  if(testDay > 0 && testDay <= daysPerMonth[month])
    return testDay;

  if(month == 2 &&      // февраль: проверка високосноо года
          testDay == 29 &&
              (year % 400 == 0 || (year %4 == 0 && year % 100 != 0)))
    return testDay;

  cout<<"  DENY:  "<<testDay<<" NEPRAVILNIY. USTANOVITY DENY 1 \n\n";

  print();
  print_Day_StringMonth_Year();

  return 1;          // если значение неправильное
}
// Проверка и Установка даты через setDate------------------------------------
void Date::setDate(int dy, int mn, int yr)
{
  if(mn > 0 && mn <= 12)    // проверка месяца
    month = mn;
  else{
    month = 1;
    cout<<"  MEZYAC: "<<mn<<" NEPRAILNIY. USTANOVITY MEZYAC 1. \n\n";
    }
  year = yr;
  day = checkDay(dy);      // проверка дня

  print();
  print_Day_StringMonth_Year();

  cout<<"\n  KONSTRUKPOR OBEKTA 'DATE'\n";
  cout<<endl;
}
// деструктор-----------------------------------------------------------------
Date::~Date()
{
  cout<<"  DESTRUKTOR DATE-OBEKTA DLA DATY ";
  print();
  cout<<endl;
}

//---------------------------------------------------------------------------

// демонстрация композиции: объект с объектами-членами
#include <iostream.h>
using std::cout;
using std::cin;
using std::endl;

#include "date.h"
int main()
{
  int dayy,
      monthh,
      yearr,
      z;

  Date d(3, 12, 1988);
  cout<<'\n';

  // Формат 05.01.1997
  d.print();

  cout<<'\n';

  // Формат 5 января 1997 года.
  d.print_Day_StringMonth_Year();

  cout<<"\n  PROVERKA KONSTRUKTORA 'DATE' S NEPRAVILYNIVI ZNACHENIAVI:  \n";
  Date dd(14, 35, 1994);      // неправильные Date-значения
  cout<<endl;

  do{
    cout<<"\n Enter '0' START AND '-1' FINISH: ";
    cin>>z;

    cout<<endl;

    // Ввод нужных значений
      cout<<"Enter Day: ";
      cin>>dayy;
      cout<<"Enter Month: ";
      cin>>monthh;
      cout<<"Enter Year: ";
      cin>>yearr;

      // Функция установки и проверки правильности ввода
      d.setDate(dayy, monthh, yearr);

      // Вывод вариантов отображения
      d.print();
      d.print_Day_StringMonth_Year();
      }
  while(z != -1);

  cin>>z;
        return 0;
}
//---------------------------------------------------------------------------


El Scorpio 21-07-2010 01:45 1457182

Цитата:

Цитата котвася
Так что думаю тут без * никак так как надо передавать массив. Или есть другой "правильный путь"? »

Для работы со строками нужно использовать классы строковых контейнеров. Управляться с "символьными массивами" под силу только профессионалам, ибо там легко допустить ошибку,*которая сделает программу неработоспособной.


Код:

#include <strings.h>

class Date
{
public:
        Date (int, const string &, int);
        Date(int, int);
        Date(int, int, int);
       
        void print() const;
        void printChar() const;
        void setDate(int, int, int);
private:
        int Fday;
        int Fmonth;
        string Fsmonth;
        int Fyear;
};


Date::Date(int dd, const string &mm, int yyyy)
{
        Fday = dd;
        year = yyyy;
        Fmonth = mm; // копирование строки выполняется переопределённым оператором класса
}

В Borland C++ Builder для работы со строками обычно используется класс AnsiString
Опять же, нет нужды хранить строковое значение месяца в объекте - ведь названия месяцев известны :)

котвася 24-07-2010 23:20 1460099

не знаю, по моему это сложнее, т.к. я до первого додумался первее и сам.
P.S.
в MVS надо использовать <string>


Время: 19:11.

Время: 19:11.
© OSzone.net 2001-