1

In main(), I am making an array myAppointments, and realize to make it work I would need to create a default constructor in Appointments.h, but when I do I get this error:

no matching function for call to 'Time::Time()'
Appointment(){

Here is Main:

/*
 * Homework 4  -- UPDATE as needed
*/ 
    
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
    
#include "Appointment.h"
using namespace std;
    
void callPrint (Time &TimeOrApptObject) { TimeOrApptObject.print(); }

int main(){
    int month, day, year, hour, minute,howLong;
    Appointment  myAppointments[19];
    
    ifstream HW4DataFileHandle;
    
    HW4DataFileHandle.open("Lab6Data.txt");
    while (!HW4DataFileHandle.eof( )) {
        for (int i = 1; i < 20; i++) {
            HW4DataFileHandle>>month;
            HW4DataFileHandle>>day;
            HW4DataFileHandle>>year;
            HW4DataFileHandle>>hour;
            HW4DataFileHandle>>minute;
            HW4DataFileHandle>>howLong;
            myAppointments[i] = Appointment( month, day, year, hour, minute, howLong);
        }
        cout <<"enter a month" <<endl;
        cin >> month;
        cout <<"enter a day" <<endl;
        cin >> day;
        cout <<"enter a year"<<endl;
        cin >> year;
        Date myDate( month, day, year);
    
        cout <<"Appointments for" << month <<"/" << day <<"/" << year <<":"<< endl;
    
        for (int i = 0; i <13; i++){
            if ( myAppointments[i]==Date myDate )
            {
                Time thisTime = myAppointments[i];
                thisDate.print();
                cout << endl;
            } 
        }
    }

And here are the header files:

Date.H

// Date.h -- Class Date    UPDATE  as needed
#ifndef DATE_H
#define DATE_H

class Date  {  
private:
    int month;
    int day;
    int year;
public:
    Date(int m, int d, int y) : month(m), day(d), year(y)
    {
    }

    friend bool friendTorCompare2Dates (const Date&,const Date& );
};

bool friendTorCompare2Dates (const Date& Right, const Date& Left)
{
    if (Right.month == Left.month && Right.day == Left.day )
        return true;
    else
        return false;
}
    
#endif

Time.H

//Time.h -- Class Time UPDATE  as needed
using namespace std;
#include<iostream>
#ifndef TIME_H
#define TIME_H

class Time {
private :
    int hour; int minute;
public:
    Time(int h, int m) : hour(h)
    {
    }
    virtual void print() {
        cout << hour << " " << minute <<" "  ;
    }
};

#endif

Appointment.h

// Appointment.h -- Class Appointment   UPDATE as needed
//
    
using namespace std;
#include "Time.h"
#include "Date.h"
#ifndef APPOINTMENT_H
#define APPOINTMENT_H

class Appointment:  public Date, public Time {  
private:
    int howLong;
public:
    Appointment(int month, int day, int year, int hour, int minute, int howLong) : 
        Date(month, day, year), Time(hour, minute), howLong(howLong)
    {
    }

    Appointment(){
        month;
        day;
        year;
        hour;
        minute;
        howLong;    
    }
};
        
#endif

What do I need to change in order to have my default constructor in Appointment work? If you notice any thing else, or have any other questions in regards to my question, please let me know. I would appreciate it if you would include an example in your answer.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
MR Hones
  • 61
  • 9
  • `Appointment()` needs to call the base-class constructors, which do not have parameterless constructors. You need to figure out with what "default values" this constructor should call them – UnholySheep Aug 06 '20 at 21:36
  • 2
    I will now repeat my warning about `while (!HW4DataFileHandle.eof( ))`. [It's a bug you'll find later.](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – user4581301 Aug 06 '20 at 21:54
  • Your header guards in `Time.H` and `Appointment.h` are not setup properly. The `#ifndef ... #define ...` part needs to be at the very top. All of the `#include` and `using namespace std;` statements need to be inside the `ifndef ... #endif` block – Remy Lebeau Aug 06 '20 at 22:09
  • @MRHones you will have to write a `==` operator overload. Some help on doing that here: [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading) – user4581301 Aug 06 '20 at 22:33

2 Answers2

4

This line:

Appointment  myAppointments[19];

will call the default constructor of Appointment for each element.

Your default constructor doesn't explicitly call a constructor of Time, so the default constructor of Time will be called, which doesn't exist. Same with Date.

You can reinstate the default constructor like this:

class Time {
 // ...
 public:
  Time() = default;
};

To get reasonable default behavior, you should provide default initial values for the members of your class, e.g.

class Time {
 private :
   int hour = 0; 
   int minute = 0;
public:
   // ...
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
cigien
  • 57,834
  • 11
  • 73
  • 112
  • Ha! It's Baaaa-ack! Can't keep a good answer down, eh? – user4581301 Aug 06 '20 at 21:41
  • @user4581301 Haha, yeah, I thought OP was actually asking this originally, and figured they'd get around to it eventually ;) – cigien Aug 06 '20 at 21:42
  • Asker dropped a comment asking about this problem in the last question, so I pointed them at your answer only to find it had been deleted. Then they deleted the comment, and I figured the same as you. It'd show up sooner or later. – user4581301 Aug 06 '20 at 21:46
  • @user4581301 Edited the answer a bit. – cigien Aug 06 '20 at 21:53
1

When you declare the array Appointment myAppointments[19];, the default constructor for Appointment is used immediately for all 19 elements. However, Date and Time do not have default constructors defined, but Appointment's default constructor will try to call them both implicitly, hence the error you are seeing since they don't exist.

So, you have 4 different ways to fix this:

  1. make Appointment's default constructor call Date's and Time's non-default constructors explicitly (just like your other Appointment constructor does), passing in default values to them:

    Appointment() : 
        Date(0, 0, 0), Time(0, 0), howLong(0)
    {
    }
    
  2. give Date and Time their own default constructors, eg:

    class Date  {  
    private:
        int month;
        int day;
        int year;
    public:
        Date() : month(0), day(0), year(0)
        {
        }
    
        Date(int m, int d, int y) : month(m), day(d), year(y)
        {
        }
    
        ...
    };
    
    class Time {
    private :
        int hour;
        int minute;
    public:
        Time() : hour(0), minute(0)
        {
        }
    
        Time(int h, int m) : hour(h), minute(m)
        {
        }
    
        ...
    };
    

    Alternatively:

    class Date  {  
    private:
        int month;
        int day;
        int year;
    public:
        Date(int m = 0, int d = 0, int y = 0) : month(m), day(d), year(y)
        {
        }
    
        ...
    };
    
    class Time {
    private :
        int hour;
        int minute;
    public:
        Time(int h = 0, int m = 0) : hour(h), minute(m)
        {
        }
    
        ...
    };
    

    Alternatively (C++11 and later only):

    class Date  {  
    private:
        int month = 0;
        int day = 0;
        int year = 0;
    public:
        Date() = default;
        // or:
        // Date() : Date(0, 0, 0) {}
    
        Date(int m, int d, int y) : month(m), day(d), year(y)
        {
        }
    
        ...
    };
    
    class Time {
    private :
        int hour = 0;
        int minute = 0;
    public:
        Time() = default;
        // or:
        // Time() : Time(0, 0) {}
    
        Time(int h, int m) : hour(h), minute(m)
        {
        }
    
        ...
    };
    
  3. construct the array elements explicitly using placement-new so you can use Appointment's non-default constructor on them, eg:

    typedef unsigned char AppointmentBuf[sizeof(Appointment)];
    // better:
    // #include <type_traits>
    // using AppointmentBuf = std::aligned_storage<sizeof(Appointment), alignof(Appointment)>::type;
    
    int main(){
        AppointmentBuf myAppointments[19];
    
        ...
    
        for (int i = 0; i < 19; i++) {
            ...
            new (&myAppointments[i]) Appointment(month, day, year, hour, minute, howLong);
        }
    
        ...
    
        for (int i = 0; i < 19; i++) {
            Appointment &appt = reinterpret_cast<Appointment&>(myAppointments[i]);
            // use appt as needed...
        }
    
        ...
    
        // cleanup
        for (int i = 0; i < 19; i++) {
            reinterpret_cast<Appointment&>(myAppointments[i]).~Appointment();
        }
    
        return 0;
    }
    
  4. Change the array to hold Appointment* pointers, and then construct the array elements dynamically via new using Appointment's non-default constructor, eg:

    int main(){
        Appointment* myAppointments[19] = {};
    
        ...
    
        for (int i = 0; i < 19; i++) {
            ...
            myAppointments[i] = new Appointment(month, day, year, hour, minute, howLong);
        }
    
        ...
    
        for (int i = 0; i < 19; i++) {
            // use myAppointments[i] as needed...
        }
    
        ...
    
        // cleanup
        for (int i = 0; i < 19; i++) {
            delete myAppointments[i];
        }
    
        return 0;
    }
    

    Alternatively (C++11 or later only):

    #include <memory>
    
    int main(){
        std::unique_ptr<Appointment> myAppointments[19];
    
        ...
    
        for (int i = 0; i < 19; i++) {
            ...
            myAppointments[i] = std::make_unique<Appointment>(month, day, year, hour, minute, howLong);
        }
    
        ...
    
        for (int i = 0; i < 19; i++) {
            // use myAppointments[i] as needed...
        }
    
        ...
    
        // no manual cleanup needed
    
        return 0;
    }
    
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770