How do I override constructor in inheritance?

This is a discussion on How do I override constructor in inheritance? within the C++ Programming forums, part of the General Programming Boards category; I'm trying to use inheritance now to make things much more organised. I have a superclass of type item and ...

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    40

    How do I override constructor in inheritance?

    I'm trying to use inheritance now to make things much more organised. I have a superclass of type item and an inheriting class of type special_item.

    The book I'm reading an example from has something like this
    Code:
    class object
    {
      object(void){...}
    };
    class object2: public object
    {
      object2(void){...}  //overrides default constructor
      object2(parameters){...}  //overloads a constructor that was not present
    };
    So in my test, I did something similar, except that I left the parameters for the second constructor (that is, the one it says is overloading the constructor) to be void. The compiler doesn't like that, as it looks just like the one immediately preceeding it.

    So what's the deal? If you want to override the constructor with a new one do you have to have different parameters? What if I want it to be void in both? Should I just give it a parameter that defaults to NULL and ignore it?

    Here is my code, if it matters.
    Code:
    class item
    {
      public:
      string name, desc;
      unsigned short int id;
      friend bool operator==(const item& lhs, const item& rhs){return (lhs.id==rhs.id);}
      item(void)
      {
        id = item_id++; name = "test"; desc = "a test object";
      }
    };
    class special_item: public item
    {
      public:
      special_item(void){}
      special_item(void)
      {
        id = item_id++; name = "special"; desc = "special, one of a kind object";
      }
    };
    (edit)
    I realise that, in this specific instance, it doesn't make a difference whether the parent class' constructor is called; but this is just a test program for learning, and I'd like to figure it out anyway.
    Last edited by Loduwijk; 03-22-2006 at 09:52 PM.

  2. #2
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Code:
      special_item(void){}
      special_item(void)
      {
        id = item_id++; name = "special"; desc = "special, one of a kind object";
      }
    Those methods have the same signature.

    Code:
      special_item(void){}
      special_item(SomeType someParamter, SomeOtherType someOtherParameter)
      {
        id = item_id++; name = "special"; desc = "special, one of a kind object";
      }
    I don't know what item_id is but I assume you got it covered.

  3. #3
    Registered User
    Join Date
    Mar 2006
    Posts
    40
    Quote Originally Posted by Tonto
    [code] special_item(void){}
    Those methods have the same signature.
    And what does that mean? What is a method signature? Do you refer to the parameter thing I mentioned?
    Code:
      special_item(void){}
      special_item(SomeType someParamter, SomeOtherType someOtherParameter)
      {
        id = item_id++; name = "special"; desc = "special, one of a kind object";
      }
    I don't know what item_id is but I assume you got it covered.
    Indeed I do, concerning item_id. It's a global variable that starts at 0, that's all.

    So I was correct, I have to have some different parameters in there? I can't override it but keep no parameters?

  4. #4
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    The signatures of your two constructors for your special_item class are the same, and the compiler would not know how to deal with it if you said something like:

    Code:
    special_item s = special_item();
    A function's signature comprises of it's name, it's parameters, and it's return type. The name and return type are automatically the same, both being constructors, and you made both the paramters to them the same, void. Just remove the constructor with the empty body most likely. Overriding cannot be done within the same class, it is a feature to specialize a function in a subclass.

    Code:
      special_item(void){}
      special_item(void)
      {
        id = item_id++; name = "special"; desc = "special, one of a kind object";
      }

  5. #5
    Registered User
    Join Date
    Mar 2006
    Posts
    40
    Quote Originally Posted by Tonto
    Overriding cannot be done within the same class, it is a feature to specialize a function in a subclass.
    The "void special_item(void){}" line is to override the parent type's constructor. I don't understand why it works this way, but I'm just following what it says in my book. Though further tests show that way to be faulty.

    Normally the superclass's constructor is called in addition to the subclass'. For example, in the following I would see both "test1" and "test2" output.
    Code:
    class object1
    {
      object1(void)
      {
        cout << "test1";
      }
    }
    class object2
    {
      object2(void)
      {
        cout << "test2";
      }
    }
    Both the constructors for the parent class and the child class are called, and I end up seeing "test1test2". But I don't want the superclass constructor to be called, rather I want only the sub-class' constructor to be called.

    The book I'm reading has an example of overriding the superclass' constructor for the subclass in the way I showed first, and that is why I was doing it that way. As I said, however, further testing has shown that to be incorrect.

    So, to recap, my question is "How do I tell it to ignore the superclass' constructor?"; or, in relation to that little example code, "How would I get it to not show test1?" Similar to the way private variables and functions are kept from their subclasses, though obviously I can't make the constructor private.

  6. #6
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    Copy exactly what you see out of the book. The code sample:

    Code:
    class object1
    {
      object1(void)
      {
        cout << "test1";
      }
    }
    class object2
    {
      object2(void)
      {
        cout << "test2";
      }
    }
    Instantiation of object 2 does not instantiate object 1. I'm guessing there might just be some small typos.

    >> though obviously I can't make the constructor private

    Why not? In your code example you just posted, you made it so. Default access for classes is private.

    >> But I don't want the superclass constructor to be called, rather I want only the sub-class' constructor to be called.

    Why?

  7. #7
    Registered User
    Join Date
    Mar 2006
    Posts
    40
    Quote Originally Posted by Tonto
    Copy exactly what you see out of the book. The code sample:
    That's my whole point; it doesn't work.

    Well, to be honest, I didn't try the entirety of the book's code example. The example I gave was not a direct quote from the book. The book's example is massive and completely unrelated. What the book's example does is actually even lengthier and more involved than what I'm trying to do.

    Either way, for supposedly overriding the base class constructor, the example in the book did what I asked about in my original post. It does the following (Yes, this one is a direct quote)
    Code:
    namespace SAMSCalculator
    {
      using namespace std;
      aPersistentTape::aPersistentTape(void)
      {
        throw
          runtime_error
          (
            string("The default constructor for aPersistentTape has been used. ") +
            string("Use only the constructor that requires the file path")
          );
      }
      aPersistentTape::aPersistentTape
        (const char *theOutputFilePath):
        myOutputFilePath(theOutputFilePath)
      {
      };
      ... //It goes on with the deconstructor here.
    };
    Instantiation of object 2 does not instantiate object 1. I'm guessing there might just be some small typos.
    But it does call the base class' constructor. The code for the constructors of both object1 and object2 are called for the single object2 that is created.
    >> though obviously I can't make the constructor private

    Why not? In your code example you just posted, you made it so. Default access for classes is private.
    And something like that example shouldn't compile. It was merely to show what I meant when I was talking about the constructors of the base and derived classes. It should be public if actually used.
    >> But I don't want the superclass constructor to be called, rather I want only the sub-class' constructor to be called.

    Why?
    As I said, in this specific instance it doesn't matter. But later on, I can think of times when it might matter.

    Take the following example, which I could easily run into if I were to turn this into a game.
    Code:
    class person
    {
      public:
      person(void)
      {
        room *room = locate(5,5,0);
        loc = room;  //loc and locate being a variable and function of mine
        for(unsigned short int index = 0; index < room->occupants.size(); index += 1)
        {
          string S(name+" popped into existence here");
          room->occupants[index].send_message(S);
          //send_message being a fictional function that would send another player the message
        };
      }
    }
    class invisible_person: public person
    {
      //This invisible_person class would be one that sneaks in silently.
      //If I have no way of abandoning person::person() then I have no way of suppressing the output there.
    }
    Anyway, that's just an example.

    On a related note, I went and spent some more time using the search feature in the hopes that someone else has had the same problem, and I found some old posts talking about constructors that seemed to imply that the superclass' constructor would only be called if you used the default constructor for the derived class (that is, the one with no parameters). I went and tested this though, and it didn't seem to pan out.

    So, is this whole thing possible? Was I on the right track to begin with?

  8. #8
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    Was I on the right track to begin with?
    So what's the deal? If you want to override the constructor with a new one do you have to have different parameters? What if I want it to be void in both? Should I just give it a parameter that defaults to NULL and ignore it?
    There are terms of art in programming and "override" is one of them. There is no "overriding" taking place in your original code. When you have two member functions of the same class with the same name(or two global functions with the same name) it's called "overloading" the function. If the function signatures(name and parameters) are identical, then the compiler has no idea which one of the functions you want to call, so you get an error. Note that the return type is not part of the function signature, and therefore functions cannot differ only by return type. (It works the same way in Java.)

    object2(void){...} //overrides default constructor
    No, it is the default constructor. A default constructor is one that has no parameters. If you do not supply any constructor for your class, then the compiler supplies an invisible default constructor for you that is equivalent to this:
    Code:
    ClassName()
    {
    }
    (The same thing happens in Java, except in Java the default constructor initializes all the members to 0. In C++, the members will contain junk values.) Since you supplied a constructor for the class, the compiler doesn't supply your class with a default constructor.

    I realise that, in this specific instance, it doesn't make a difference whether the parent class' constructor is called;
    The base/parent class constructor has to be called in order to construct the derived object. (Java has similar requirements i.e. the first line of a base class constructor must call super().) Examine the output from this code:
    Code:
    #include <iostream>
    using namespace std;
    
    class Base
    {
    public:
    	Base()
    	{
    		cout<<"Base default constructor called."<<endl;
    	}
    	
    	/*
    	Base(double d)
    	{
    		cout<<"Base (double) constructor called."<<endl;
    	}
    	*/
    };
    
    class Derived : public Base
    {
    public:
    	Derived()
    	{
    		cout<<"Derived default constructor called"<<endl;
    	}
    	Derived(int num)
    	{
    		cout<<"Derived (int) constructor called."<<endl;
    	}
    };
    
    int main()
    {
    	Derived d1;
    
    	cout<<endl;
    
    	Derived d2(10);
    
    	return 0;
    }
    Then comment out the default constructor in Base, and uncomment the Base double constructor and see what happens.

    The "void special_item(void){}" line is to override the parent type's constructor. I don't understand why it works this way, but I'm just following what it says in my book.
    First, in C++, overriding only occurs when there are virtual functions in the base class. (In Java, all the superclass public functions are virtual functions, and therefore they can be overridden.)

    Second, in C++(and Java) a function named special_item(), which is the derived class constructor name, can never override a function named item(), which is the base class constructor name--because the function names are different i.e. the most prominent part of the function signatures do not match. You could try to do this:
    Code:
    class special_item : public item
    {
    public:
    
    	special_item()
    	{
    		cout<<"Derived default constructor called"<<endl;
    	}
    	special_item(int num)
    	{
    		cout<<"Derived (int) constructor called."<<endl;
    	}
    	
    	void item()
    	{
    		cout<<"Derived Base() called."<<endl;
    	}
    };
    but it won't compile.
    Last edited by 7stud; 03-23-2006 at 08:52 AM.

  9. #9
    Registered User
    Join Date
    Mar 2006
    Posts
    40
    Thank you for confirming that for me, 7stud.

    So then, if I want to have different things happen when base and derived classes are made, and the things for the derived class should not include those for the base class, what would be a good way to go about that? Should I make an initializing function? For example...
    Code:
    class base
    {
      protected:
      initialize()
      {
        ...  //parent-only stuff here
      }
      public:
      base(void);
      {
        initialize();
      }
    };
    class derived
    {
      protected:
      initialize()
      {
        ... //child-only stuff here
      }
    };
    And let that do the altered work since that can be changed for the derived class? That is the next best way I can think of.

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    that won't work because the base class will always use base::initialize(). I would suggest something like:

    Code:
    class base
    {
    	public:
    	
    	base(void)
    	{
    		initialize();
    	}
    
    	template <class D>
    	base(D & derived)
    	{
    		derived.initialize();
    	}
    	
    	void
    	initialize(void)
    	{
    		cout << "base::initialize()" << endl;
    	}
    };
    
    class derived : public base
    {
    	public:
    
    	derived(void)
    	: base(*this)
    	{
    		
    	}
    	
    	void
    	initialize(void)
    	{
    		cout << "derived::initialize()" << endl;
    	}
    };
    
    int
    main(void)
    {
    	derived object;	
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #11
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    So then, if I want to have different things happen when base and derived classes are made, and the things for the derived class should not include those for the base class, what would be a good way to go about that? Should I make an initializing function?
    I can't make any sense of that. Why don't you describe a simple numerical example of what you want to do?

  12. #12
    Registered User
    Join Date
    Mar 2006
    Posts
    40
    Quote Originally Posted by 7stud
    I can't make any sense of that. Why don't you describe a simple numerical example of what you want to do?
    Same example as before.
    Code:
    object1
    {
      public:
      object1(void)
      {cout << "This is object1, the base class. I do not want this to be be output when you are creating an object2.\n";}
    };
    object2
    {
      public:
      object2(void)
      {cout << "This is object2, the derived class. I don't want the output from object1 to be displayed when creating this object, rather, I want only this output here displayed.";}
    };
    And then, since you said I cannot make object2 ignore object1:bject1(), my question was about having a seperate initializing function that is overridden for object2, like the following.
    Code:
    object1
    {
      protected:
      create_me(void)
      {cout << "This is object1, only to display for base objects, never for the derived object.";}
      //I don't want the above output line to display when making something of class object2
      object1(void){create_me();}
    };
    object2
    {
      protected:
      create_me(void)  //Let's override create_me so that it does something else
      {cout << "This is object2, derived from object1.";}
    };
    You don't even need to mess with object2's constructor at that point, because the base class' constructor calls create_me(), which contains what you want it to do, which is overridden for object2 so that object1::create_me() is ignored for object2.

    However, Sebastiani said that this won't work either, as object2 will have object1::create_me() called for it anyway since it is object1's constructor that is calling it.

    Either way, I have come up with a way to do it based on what you guys have said here about overriding and overloading functions. It is a modified form of the solution Sebastiani gave. Since I can overload the constructor like that and get it to call a different version of it, I figure I'll just go that route. Here is how I am doing it now.
    Code:
    object1
    {
      public:
      object1(void)
      {
        //do object1 stuff here
      }
      object1(const object1& O){}
    };
    object2
    {
      public:
      object2(void): object1(*this)
      {
        //object2 stuff
      }
    };
    And that works for what I'm after.

    Thank you very much for guiding me to this solution. It's not nearly as complicated as I thought it would have to get.

  13. #13
    Registered User
    Join Date
    Apr 2003
    Posts
    2,662
    And that works for what I'm after.
    What compiler will compile that code?

    this pointers? reference parameters? You hardly need to go to all that trouble:
    Code:
    class object1
    {
    public:
    	object1(void)
    	{
    		//obj1 stuff	
    	}
    	object1(int n)
    	{
    	}
    };
    
    class object2 : public object1
    {
    public:
    	object2(void): object1(0)
    	{
    		//obj2 stuff
    	}
    };
    Last edited by 7stud; 03-24-2006 at 05:47 AM.

  14. #14
    Registered User
    Join Date
    Mar 2006
    Posts
    40
    Quote Originally Posted by 7stud
    What compiler will compile that code?
    Which code, the last one that I said works? It was just an example, not the actual code that I have. Still, I'm using Bloodshed's Dev-C++.

    Even so, what was wrong with it that would make it not compile?
    this pointers? reference parameters? You hardly need to go to all that trouble:
    (some code here)
    Thanks much, that makes it even easier yet.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 06-08-2009, 04:03 PM
  2. Inheritance
    By mrafcho001 in forum C++ Programming
    Replies: 8
    Last Post: 03-02-2006, 03:49 PM
  3. Multiple Inheritance - Size of Classes?
    By Zeusbwr in forum C++ Programming
    Replies: 10
    Last Post: 11-26-2004, 09:04 AM
  4. inheritance and performance
    By kuhnmi in forum C++ Programming
    Replies: 5
    Last Post: 08-04-2004, 01:46 PM
  5. Inheritance vs Composition
    By Panopticon in forum C++ Programming
    Replies: 11
    Last Post: 01-20-2003, 04:41 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21