Solved

C++ Inheritance -- Formatting/Setup of Derived Class

Posted on 2006-11-27
20
689 Views
Last Modified: 2008-01-16
I am trying to get a derived class to work.  The base class is set up with several different constructors.  In the derived class, the constructor will be the same as one of the constructors in the base class.  I know that I have to enter a new constructor in the derived class, even though it is the same as one of those in the base class.  The only think I want to do differently in the derived class is to print out the data in a format not contained in the base class.
I'm clearly missing something in the coding of the derived class.  What am I missing?

// Date Class Header (Base Class)

#ifndef DATE_H
#define DATE_H

#include <ctime>
#include <cstring>

class Date {

public:
      Date();
      Date( int, int );
      Date( int, int, int );
      Date( char *, int, int );
      void setMonth( int );
      void setDay( int );
      void setYear( int );
      void printDateSlash() const;
      void printDateMonth() const;
      void printDateDay() const;
      const char *monthName() const;
      bool leapYear() const;
      int daysOfMonth() const;
      void convert1( int );
      int convert2() const;
      void convert3( const char * const );
      const char *monthList( int ) const;
      int days( int ) const;

private:
      int day; // 1-31 based on month
      int month; // 1-12 ( January-December )
      int year; // any year

}; // end class Date

#endif



// Date.cpp Implementation file (Base Class)
#include <iostream>

using std::cout;

#include <cstring>
#include <ctime>

#include "Date.h"

// Date constructor that uses functions from ctime
Date::Date()
{
      struct tm *ptr; // pointer of type struct tm
      // which holds calendar time components
      time_t t = time( 0 ); // determine the current calendar time
      // which is assigned to timePtr
      ptr = localtime( &t ); // convert the current calendar time
      // pointed to by timePtr into
      // broken down time and assign it to ptr
      day = ptr->tm_mday; // broken down day of month
      month = 1 + ptr->tm_mon; // broken down month since January
      year = ptr->tm_year + 1900; // broken down year since 1900
}

// Date constructor that uses day of year and year
Date::Date( int ddd, int yyyy )
{
      setYear( yyyy );
      convert1( ddd ); // convert to month and day
}

// Date constructor that uses month, day and year
Date::Date( int mm, int dd, int yy )
{
      setYear( yy + 1900 );
      setMonth( mm );
      setDay( dd );
}

// Date constructor that uses month name, day and year
Date::Date( char *mPtr, int dd, int yyyy )
{
      setYear( yyyy );
      convert3( mPtr );
      setDay( dd );
}

// Set the day
void Date::setDay( int d )
{ day = d >= 1 && d <= daysOfMonth() ? d : 1; }

// Set the month
void Date::setMonth( int m ) { month = m >= 1 && m <= 12 ? m : 1; }

// Set the year
void Date::setYear( int y ) { year = y >= 1900 && y <= 1999 ? y : 1900; }

// Print Date in the form: mm/dd/yyyy
void Date::printDateSlash() const
{ cout << month << '/' << day << '/' << year << '\n'; }

// Print Date in the form: monthname dd, yyyy
 void Date::printDateMonth() const
 { cout << monthName() << ' ' << day << ", " << year << '\n'; }

 // Print Date in the form: ddd yyyy
 void Date::printDateDay() const
 { cout << convert2() << ' ' << year << '\n'; }

 // Return the month name
 const char *Date::monthName() const { return monthList( month - 1 ); }

 // Return the number of days in the month
 int Date::daysOfMonth() const
 { return leapYear() && month == 2 ? 29 : days( month ); }

 // Test for a leap year
 bool Date::leapYear() const
 {
       if ( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) )
       return true;
       else
       return false;
 }

 // Convert ddd to mm and dd
 void Date::convert1( int ddd ) // convert to mm / dd / yyyy
 {
       int dayTotal = 0;

       if ( ddd < 1 || ddd > 366 ) // check for invalid day
       ddd = 1;

       setMonth( 1 );

       for ( int m = 1; m < 13 && ( dayTotal + daysOfMonth() ) < ddd; ++m ) {
             dayTotal += daysOfMonth();
             setMonth( m + 1 );
       }

       setDay( ddd - dayTotal );
       setMonth( m );
 }

 // Convert mm and dd to ddd
 int Date::convert2() const // convert to a ddd yyyy format
 {
       int ddd = 0;

       for ( int m = 1; m < month; ++m )
       ddd += days( m );

       ddd += day;
       return ddd;
 }

 // Convert from month name to month number
 void Date::convert3( const char * const mPtr ) // convert to mm / dd / yyyy
 {
       bool flag = false;

       for ( int subscript = 0; subscript < 12; ++subscript )
       if ( !strcmp( mPtr, monthList( subscript ) ) ) {
             setMonth( subscript + 1 );
             flag = true; // set flag
             break; // stop checking for month
       }

       if ( !flag )
       setMonth( 1 ); // invalid month default is january
 }

 // Return the name of the month
 const char *Date::monthList( int mm ) const
 {
       char *months[] = { "January", "February", "March", "April", "May",
       "June", "July", "August", "September", "October",
       "November", "December" };

       return months[ mm ];
 }

 // Return the days in the month
 int Date::days( int m ) const
 {
       const int monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

       return monthDays[ m - 1 ];
 }



//EuroDate.h -- header file for derived class
#ifndef EURODATE_H
#define EURODATE_H

#include <ctime>
#include <cstring>

#include "Date.h"

class EuroDate : public Date
{
public:
      EuroDate(int, int, int);
      print EuroDateSlash() const;


private:
      int day;
      int month;
      int year;

};
#endif

//EuroDate.cpp -- implementation file for derived class
#include <iostream>

using std::cout;

#include <cstring>
#include <ctime>

#include "EuroDate.h"


EuroDate::EuroDateSlash(int mm, int dd, int yy)
:Date(mm,dd,yy)

void EuroDate::printEuroDateSlash() const
{
      cout << day << '/' << month << '/' << year << '\n';
}

0
Comment
Question by:webbps
  • 9
  • 7
  • 2
  • +1
20 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 18021080
Just a few minor glitches, then it compiles fine:

//EuroDate.h -- header file for derived class
#ifndef EURODATE_H
#define EURODATE_H

#include <ctime>
#include <cstring>

#include "Date.h"

class EuroDate : public Date
{
public:
     EuroDate(int, int, int);
     void printEuroDateSlash() const; // instead of "print EuroDateSlash() const;"


private:
     int day;
     int month;
     int year;

};
#endif

//EuroDate.cpp -- implementation file for derived class
#include <iostream>

using std::cout;

#include <cstring>
#include <ctime>

#include "EuroDate.h"


EuroDate::EuroDate(int mm, int dd, int yy) // no 'Slash' in constructor name, causes error
:Date(mm,dd,yy) {} // constructor needs a body

void EuroDate::printEuroDateSlash() const
{
     cout << day << '/' << month << '/' << year << '\n';
}
0
 
LVL 14

Expert Comment

by:wayside
ID: 18039299
Your Date class has private member variables of day, month, and year.

Your derived EuroDate class also has private member variables of day, month, and year, which will "hide" the ones in the base class.

The EuroDate constructor will call the base class constructor, which will initialize Date's day, month, and year, but the EuroDate's day, month and year will not get initialized. So your printEuroDateSlash() function will not do what you expect.

Most likely, you should make day, month, and year be protected in the Date class (instead of private), and not have them at all in your EuroDate class. That way the derived class can use the members from the base class.

0
 

Author Comment

by:webbps
ID: 18039492
Thank you both jkr & wayside.  jkr got me started down the right path, and I expanded my program to include setting up new constructors in the derived class, so that all dates print out in dd/mm/yyy, ddd yyyy, dd Month, yyy formats of the base class.  However, the printing did not work as I had expected, and this is likely because the data members of day, month and year are declared private in the base class -- hence, wayside's comment.  If I understand wayside correctly, in order to work properly, the various public functions would still need to be added to the derived class ( I will try ths)?  I now know that this was the entire point of this exercise, to show the impact of private inheritance vs protected.  My next assignment is to write the program declaring the data members protected -- bet it works!
0
 
LVL 14

Accepted Solution

by:
wayside earned 500 total points
ID: 18039696
> in order to work properly, the various public functions would still need to be added to the derived class

No. That's the beauty of inheritance - you get to use all of the functions in the base class, and add more functions (or override base class functions) in the derived class.

The only functions you need to add to the derived class are new functions that don't exist in the base class, and functions with the same name as a base class function but whose behavior you want to change.

For example, instead of having a function named "printEuroDateSlash" in your EuroDate class, you should override the printDateSlash() function in your EuroDate class (declare it as virtual in the base class), and give it the correct behavior for a EuroDate.

Then, you can just call the "printDateSlash" function, and no matter what kind of date you created, the correct function will get called.

For example:

Date a(12,25,2006);
a.printDateSlash();     // calls Date's printDateSlash function

EuroDate b(12, 25, 2006);
b.printDateSlash();    // calls EuroDate's printDateSlash function

Date *c = new EuroDate(12,25, 2006);
c->printDateSlash();   // <- what gets called here? if printDateSlash() is declared as virtual, Date's printDateSlash() gets called.
0
 

Expert Comment

by:khall16
ID: 18627341
I tried running the program with jkr's comments and am not able to do so.  All of my files look identical to the above.  I changed Date.H to contain protected members instead of private members, and it still did not work.  Is there a solution posted somewhere for this?  I am really trying to understand this by keeping the members in Date.H as private.
0
 
LVL 86

Expert Comment

by:jkr
ID: 18627388
What errors are you getting?
0
 

Expert Comment

by:khall16
ID: 18627517
--------------------Configuration: Date - Win32 Debug--------------------
Compiling...
Date-Main.cpp
C:\Kall16\Date-Main.cpp(20) : error C2661: 'EuroDate::EuroDate' : no overloaded function takes 2 parameters
C:\Kall16\Date-Main.cpp(21) : error C2664: '__thiscall EuroDate::EuroDate(int,int,int)' : cannot convert parameter 1 from 'char [9]' to 'int'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
C:\Kall16\Date-Main.cpp(22) : error C2512: 'EuroDate' : no appropriate default constructor available
Error executing cl.exe.

Date-Main.obj - 3 error(s), 0 warning(s)
******************************************************


// Date-Main.cpp
// Create and manipulate a Date objects.
#include <iostream>
#include <stdlib.h>
using std::cout;
using std::endl;

#include "EuroDate.h" // include definition of class Date

// function main begins program execution
 int main()

 {
       Date date1( 6, 28, 88 ),
         date2( 228, 1960 ),
       date3( "November", 5, 1941 ),
         date4;

       EuroDate d1( 6, 28, 88 ),
         d2( 228, 1960 ),
       d3( "November", 5, 1941 ),
         d4;


  date1.printDDDYYYY(); // print in the format ddd yyyy
  date2.printDDDYYYY();
  date3.printDDDYYYY();
  date4.printDDDYYYY();
  cout << '\n';

  date1.printMMDDYY(); // print in the format mm/dd/yy
  date2.printMMDDYY();
  date3.printMMDDYY();
  date4.printMMDDYY();
  cout << '\n';

  date1.printMONTHDDYYYY(); // print in the format "month" d, yyyy
  date2.printMONTHDDYYYY();
  date3.printMONTHDDYYYY();
  date4.printMONTHDDYYYY();
  cout << endl;

  d1.printDDMMYYYY(); // print in the format dd/mm/yyyy
  d2.printDDMMYYYY();
  d3.printDDMMYYYY();
  d4.printDDMMYYYY();
  cout << endl;

 
  system("pause");

  return 0;
 }
0
 
LVL 86

Expert Comment

by:jkr
ID: 18627624
You have to provide the constructors that take more than one parameter for 'EuroDate' explicitly, they aren't inherited from 'Date' by default. Just make that

//#include "Date.h"

class EuroDate : public Date
{
public:
     // just call the base class constructors
     EuroDate(int n1, inn2t,) : Date(n1,n2) {};
     EuroDate(int n1, int n2, int n3) : Date(n1,n2,n3) {};
     EuroDate(char* p, int n1, int n2) : Date(p, n1,n2) {};

     // ... rest here
};
0
 

Expert Comment

by:khall16
ID: 18627956
Compiling...
EuroDate.cpp
C:\Kall16\EuroDate.cpp(14) : error C2011: 'EuroDate' : 'class' type redefinition
Error executing cl.exe.

EuroDate.obj - 1 error(s), 0 warning(s)

********************************************************************
// EuroDate.cpp -- Implementation File for derived class
// Member-function definitions for class Time.
#include <iostream>

using std::cout;

#include <cstring>
#include <ctime>

#include "EuroDate.h"


class EuroDate : public Date// EuroDate constructor
{


public:
     // calling the base class constructors
      EuroDate(int ddd, int yyyy,) : Date(ddd,yyyy) {};
      EuroDate(int mm, int dd, int yy) : Date(mm,dd,yy) {};
      EuroDate(char* mPtr, int dd, int yyyy) : Date(mPtr, dd,yyyy) {};


      // Print Date in the form: ddd yyyy
 void EuroDate::printDDMMYYYY() const
 { cout << day << '/' << month << '/' << year << '\n'; }



};
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Expert Comment

by:khall16
ID: 18627979
I think I figured out what I did wrong above.  Let me fix.
0
 
LVL 86

Expert Comment

by:jkr
ID: 18627998
Shouldn't that be

#include "Date.h"

?

Otherwise the compiler will see 'EuroDate' twice, thus the error.

0
 

Expert Comment

by:khall16
ID: 18628202
// EuroDate.h
// EuroDate class definition derived from Date Class
// Member-function definitions appear in EuroDate.cpp.
#include <string> // program uses C++ standard string class
using std::string;
#include <ctime>
#ifndef EURODATE_H
#define EURODATE_H

#include "Date.h"

// EuroDate class definition
class EuroDate : public Date
{
public:
     // calling the base class constructors
      EuroDate(int ddd, int yyyy,) : Date(ddd,yyyy) {};
      EuroDate(int mm, int dd, int yy) : Date(mm,dd,yy) {};
      EuroDate(char* mPtr, int dd, int yyyy) : Date(mPtr, dd,yyyy) {};

   void printDDMMYYYY() const; // print date in MM/DD/YYYY format
//private:
   int month; // 1-12 (Januarhy - December)
   int day; // 1-31 based on month
   int year; // any year

}; // end class EuroDate  

#endif
****************************
// EuroDate.cpp -- Implementation File for derived class
// Member-function definitions for class Time.
#include <iostream>

using std::cout;

#include <cstring>
#include <ctime>

#include "EuroDate.h"


EuroDate::EuroDate( int mm, int dd, int yy ):Date( mm,dd,yy )

      // Print Date in the form: ddd yyyy
void EuroDate::printDDMMYYYY() const
 { cout << day << '/' << month << '/' << year << '\n'; }

*********************************************
Compiling...
EuroDate.cpp
c:\kall16\eurodate.h(18) : error C2629: unexpected 'class EuroDate ('
c:\kall16\eurodate.h(18) : error C2334: unexpected token(s) preceding ':'; skipping apparent function body
C:\Kall16\EuroDate.cpp(16) : error C2612: trailing 'auto' illegal in base/member initializer list
C:\Kall16\EuroDate.cpp(17) : error C2601: 'printDDMMYYYY' : local function definitions are illegal
C:\Kall16\EuroDate.cpp(19) : fatal error C1004: unexpected end of file found
Error executing cl.exe.

EuroDate.obj - 5 error(s), 0 warning(s)


0
 
LVL 86

Expert Comment

by:jkr
ID: 18628295
There's one comma too much in

      EuroDate(int ddd, int yyyy,) : Date(ddd,yyyy) {};

Make that

      EuroDate(int ddd, int yyyy) : Date(ddd,yyyy) {};

Also, if you want to separately add the constructors in your implementation fil4e, make that

// EuroDate class definition
class EuroDate : public Date
{
public:
     // calling the base class constructors
      EuroDate(int ddd, int yyyy);
      EuroDate(int mm, int dd, int yy);
      EuroDate(char* mPtr, int dd, int yyyy);

   void printDDMMYYYY() const; // print date in MM/DD/YYYY format
//private:
   int month; // 1-12 (Januarhy - December)
   int day; // 1-31 based on month
   int year; // any year

}; // end class EuroDate

and

EuroDate::EuroDate(int ddd, int yyyy,) : Date(ddd,yyyy)
{
}

EuroDate::EuroDate(int mm, int dd, int yy) : Date(mm,dd,yy)
{
}

EuroDate::EuroDate(char* mPtr, int dd, int yyyy) : Date(mPtr, dd,yyyy)
{
}

0
 

Expert Comment

by:khall16
ID: 18628503
Int Main stated that I didn't have appropriate default constructor available.  I commented out those portions and everything compiles.  When I execute, the results are bad.  The three dates for EuroDate are all the same and meaningless.
0
 

Expert Comment

by:khall16
ID: 18629020
Never mind...I finally figured it out.  :-)
Thanks for your help!!!!
0
 
LVL 86

Expert Comment

by:jkr
ID: 18629734
You're most welcome. BTW, when a questio is solved, you should close it.
0
 
LVL 86

Expert Comment

by:jkr
ID: 18650768
Sorry, what's up here?
0
 
LVL 86

Expert Comment

by:jkr
ID: 18650774
Uh, duplicate accounts also. Will address customer service....
0
 
LVL 86

Expert Comment

by:jkr
ID: 18724446
Closing comment:

Actually, no. Since that whole review request was based on the assumption that this Q was being gone through by one asker, it became unnecessary once it was known that this was caused by just one person taking advantage of the situation. I will learn to pay more attention on who posted what to not get screwed again in the future ;o)

(from http://www.experts-exchange.com/Community_Support/General/Q_22427013.html)
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now