1

I have the following snippet of code:

const int DATE_LENGTH = 6;

class BaseClass {
    protected:
        int date[DATE_LENGTH];
        int year;
    public:
        BaseClass(){}
        BaseClass(int *d) {
            for (int i = 0; i < DATE_LENGTH; i++) { date[i] = d[i];}
            year = 1900 + date[4] * 10 + date[5];
        }
        void printYear() {
            cout << year << endl;
        }
};

class DerivedClass : public BaseClass {
    public:
        DerivedClass() {}
        void printYear() {
            cout << year << endl;
        }
};

int main(int argc, char *argv[]) {
    int dob[] = {1, 6, 1, 0, 9, 0};
    BaseClass base(dob);
    base.printYear(); // prints 1990

    DerivedClass derived;
    derived.printYear(); // prints 1439156608
}

I'm having trouble understanding why the output from printYear() in my derived class is outputting junk. Am I missing something very obvious?

Any help would be appreciated!

6
  • Your default constructors don't initialize anything, so you get whatever happens to be in memory. Commented Jul 6, 2014 at 22:41
  • 2
    @T.C.: That's not quite true, the base subobject did get initialized. The language mandates that this happens. It's just that a very poor initialization was chosen.
    – Kerrek SB
    Commented Jul 6, 2014 at 22:44
  • 1
    @RetiredNinja: That's not actually something you can guarantee. It's undefined behaviour, and you might get something from memory, or a pizza, or lose your job.
    – Kerrek SB
    Commented Jul 6, 2014 at 22:45
  • 1
    You can get pizzas from undefined behaviour? Full speed ahead!
    – chris
    Commented Jul 6, 2014 at 22:46
  • @KerrekSB You're right, I demand my pizza! :) Commented Jul 6, 2014 at 22:47

3 Answers 3

4

Your program has undefined behaviour. The default constructor of DerivedClass, which you are using, does not initialize the year member.

If you wanted to initialize the base member, you could do that by calling an appropriate base constructor, or by assigning the value directly.

DerivedClass() { year = 1999; }
2
  • Are you absolutely sure that's UB and cannot just be unspecified values? Commented Jul 6, 2014 at 22:46
  • @Deduplicator, Yes, year is uninitialized and an lvalue-to-rvalue conversion is performed on it.
    – chris
    Commented Jul 6, 2014 at 22:47
2

The default constructor of class BaseClass

BaseClass(){}

does not initislize data members date and year

This default constructor is called by the default constructor of class DerivedClass when you create object derived

DerivedClass derived;

So these data members have arbitrary values and your program has undefined behaviour.

Change the derived class the following way

class DerivedClass : public BaseClass {
    public:
        using BaseClass::BaseClass;
        DerivedClass() {}
        void printYear() {
            cout << year << endl;
        }
};

and create object derived as

DerivedClass derived( dob );

Or instead of the using declaration you can yourself explicitly define a constructor in class DerivedClass that has one parameter of type int * and calls the corresponding constructor of the base class. For example

class DerivedClass : public BaseClass {
    public:
        DerivedClass() {}
        DerivedClass( int *d ) : BaseClass( d ) {}
        void printYear() {
            cout << year << endl;
        }
};
0

The other provided answers only deal with part of the issue, partly because the date itself is never defined in the DerivedClass default constructor of either currently provided, and the other part being the BaseClass default constructor still has no defined value for either class variable (date or year). If the following code is used, depending what the default date and year should be, no additional change is actually required for the DerivedClass.

#include <iostream>

using namespace std;

const int DATE_LENGTH = 6;

class BaseClass {
    protected:
        int date[DATE_LENGTH];
        int year;
    public:
        BaseClass()
        {
            int date[] = {1, 6, 1, 0, 9, 0};
            year = 1900 + date[4] * 10 + date[5];
        }
        BaseClass(int *d)
        {
            for (int i = 0; i < DATE_LENGTH; i++) { date[i] = d[i];}
            year = 1900 + date[4] * 10 + date[5];
        }
        void printYear() {
            cout << year << endl;
        }
};

class DerivedClass : public BaseClass {
    public:
        DerivedClass() {}
        void printYear() {
            cout << year << endl;
        }
};

int main(int argc, char *argv[])
{
    int dob[] = {1, 6, 1, 0, 9, 0};
    BaseClass base(dob);
    base.printYear(); // prints 1990

    DerivedClass derived;
    derived.printYear(); // prints 1439156608
    return 0;
}

Application Output

1990
1990

Not the answer you're looking for? Browse other questions tagged or ask your own question.