Thread: new Object() and &Object()

  1. #1
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629

    new Object() and &Object()

    Hello.
    1.
    I was wondering why is new Object() different from &Object()?
    Code:
    #include <iostream>
    #include <vector>
    using namespace std ;
    class Base
    {
    public: 
    	int num ;
    	Base()
    	{
    		cout << "Constructor for Base class" << endl;
    	}
    	void NotVirtual()
    	{
    		cout << "Base, Not Virtual" << endl ;
    	}
    
    	virtual void Virtual()
    	{
    		cout << "Base, Virtual"  << endl ;
    	}
    	~Base()
    	{
    		cout << "Destructor for Base class" << endl;
    	}
    } ;
    
    class Derived: public Base
    {
    public:
    	Derived():Base() 
    	{
    		cout << "Constructor for Derived class" << endl;
    	}
    	void NotVirtual()
    	{
    		cout << "Derived, Not Virtual" << endl ;
    	}
    
    	void Virtual()
    	{
    		cout << "Derived, Virtual" << endl;
    	}
    
    	~Derived()
    	{
    		cout << "Destructor for Derived class" << endl;
    	}
    }	;
    the keyword virtual says the function that is called, depends not on the type of pointer (or reference) but on the type of object.
    And in order for polymorphism to work..we need pointers..

    Code:
        Base *b[3] ;
        
        b[0] = &Derived() ;
        b[1] = new Derived() ;
        b[2] = new Base() ;
    If I was to run this code...
    the function call for b[1] and b[2] execute correctly..but b[0] doesn't, as in instead of printing "Derived constructor" It prints "Base constructor"..
    In fact, the only difference between & and new i could see was that
    &Derived() called the default destructor for base and derived class.
    so if b[0] holds an invalid reference to &Derived(), since the object would have been destroyed..why do I not get a seg fault?
    But since I didn't..why does it not print "Derived constructor" ? After the type of object is Derived()..
    can you please clarify thanks. And your reply shouldn't make me lose my hair, although at this stage... :O
    You ended that sentence with a preposition...Bastard!

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If you just do b[0] you should see
    Code:
    Constructor for Base class
    Constructor for Derived class
    Destructor for Derived class
    Destructor for Base class
    and I don't know what else you were hoping to see.

  3. #3
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by tabstop View Post
    If you just do b[0] you should see
    Code:
    Constructor for Base class
    Constructor for Derived class
    Destructor for Derived class
    Destructor for Base class
    and I don't know what else you were hoping to see.

    yep, that is exactly what I saw..but what I don't get is
    oh here..the code
    Code:
    	cout << endl << endl;
    	for(int i=0;i<3;i++)
    	{
    		b[i]->Virtual() ;
    	}
    Now, that will print for
    b[0], "Base, Virtual"
    b[1], "Derived, Virtual"
    b[2], "Base, Virtual"

    if the type of function that is to be called depends on the type of object and not the handle because I used virtual keyword then
    b[0] should print "Derived, Virtual"..but it doesn't and I have no idea why.
    And also, as you noticed that it calls the destructor for &Derived()
    why is it that when I accessed it, b[0]->Virtual() the program didn't crash..
    You ended that sentence with a preposition...Bastard!

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The program is not obligated to crash just because you've done something silly. It can crash, but it doesn't have to. It can do whatever the heck it wants.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Sometimes your destructor needs to be virtual, and this is one of those times. See here: [20] Inheritance -- virtual functions Updated! , C++ FAQ

  6. #6
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by tabstop View Post
    The program is not obligated to crash just because you've done something silly. It can crash, but it doesn't have to. It can do whatever the heck it wants.
    ah, a bit of Skynet there huh?

    so any idea why it prints Base, Virtual as opposed to Derived, Virtual?
    You ended that sentence with a preposition...Bastard!

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Eman View Post
    so any idea why it prints Base, Virtual as opposed to Derived, Virtual?
    Because b[0] is not pointing at a Derived object? Why would you expect it to call Derived when there's no Derived object there?

  8. #8
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by tabstop View Post
    Because b[0] is not pointing at a Derived object? Why would you expect it to call Derived when there's no Derived object there?
    Code:
    b[0] = &Derived() ;
    This code is invalid I know..but since it "appears" to work..it is pointing at a Derived object.
    yet..it prints "Base, Virtual"
    You ended that sentence with a preposition...Bastard!

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Just running this

    Base *b = &Derived();
    (*b).Virtual();

    produces

    Constructor for Base class
    Constructor for Derived class
    Destructor for Derived class
    Destructor for Base class
    Base, Virtual

    Which means that what happened here is you took the address of a temporary object that was destroyed before the questionable call, anyway. Even though it apparently produces no crash, it's not correct.

  10. #10
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    Sometimes your destructor needs to be virtual, and this is one of those times. See here: [20] Inheritance -- virtual functions ..Updated!.., C++ FAQ
    oh, I just saw your post...I will read it now
    EDIT:
    I didn't even know a destructor can be made virtual..I thought the didn't have types?
    and again...the program shows that compiler both calls the base and and derived destructors...
    Which means that what happened here is you took the address of a temporary object that was destroyed before the questionable call, anyway. Even though it apparently produces no crash, it's not correct.
    is the object not destroyed...after getting the address, on reaching the ;?
    so the OS compensates, by choosing the Base class Virtual function?
    Last edited by Eman; 01-30-2011 at 11:11 AM.
    You ended that sentence with a preposition...Bastard!

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Eman View Post
    Code:
    b[0] = &Derived() ;
    This code is invalid I know..but since it "appears" to work..it is pointing at a Derived object.
    It is doing no such thing. Remember: virtual is a run-time check, not a compile-time check. The fact that the last thing b[0] validly pointed to was a Derived object is not relevant, and the fact that the compiler can "see" that if b[0] points to anything valid, it used to be a Derived object is really not relevant. When you get to this code as the program is running, the program goes to that memory location and queries the object there for its type. Since in this case there is no object there to return any information, the program continues on its way using the type you told it was there (a Base). (And note that this last sentence is just based on the observed behavior: the program could do anything it wanted in this situation, including crash.)

  12. #12
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by tabstop View Post
    It is doing no such thing. Remember: virtual is a run-time check, not a compile-time check. The fact that the last thing b[0] validly pointed to was a Derived object is not relevant, and the fact that the compiler can "see" that if b[0] points to anything valid, it used to be a Derived object is really not relevant. When you get to this code as the program is running, the program goes to that memory location and queries the object there for its type.
    So it is the keyword virtual that makes it polymorphic, dynamic binding? I thought it was just there to enable it to override the base class function and call the derived classes function.

    Since in this case there is no object there to return any information, the program continues on its way using the type you told it was there (a Base).
    I get what you said above so far..but can you clarify "the type you told it was there".
    You mean it uses the type of the pointer?
    You ended that sentence with a preposition...Bastard!

  13. #13
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I didn't even know a destructor can be made virtual..I thought the didn't have types?
    I'm not sure what you mean -- I think you are talking about return types; which, in that case, you are right -- but virtual is not a type. It is a keyword.

    and again...the program shows that compiler both calls the base and and derived destructors...
    As the FAQ tried to explain, delete p is not necessarily resulting in the type of p's destructor being called (first). If you have a virtual destructor, a run-time check for the type will occur and result in the correct destructors being called, which makes the delete a well defined operation. If you depend on undefined behavior, then simply because something good happens on your machine and the result is good for you, doesn't mean that when I compile it I will get the same result.

    Let's take this code:

    Base *p = new Derived;
    delete p;

    Along with the code you originally posted, I get

    Constructor for Base class
    Constructor for Derived class
    Destructor for Base class

    No Derived destructor call for this object. So there's a lesson in undefined behavior today.

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Eman View Post
    So it is the keyword virtual that makes it polymorphic, dynamic binding? I thought it was just there to enable it to override the base class function and call the derived classes function.
    "polymorphic, dynamic binding" is the same as "override the base class function and call the derived classes function", at least in the sense of "even though we're holding a base class pointer here". Without virtual, you'd always get Base class functions whenever you called from a Base class pointer, regardless of what was actually being pointed to.

    Quote Originally Posted by Eman View Post
    I get what you said above so far..but can you clarify "the type you told it was there".
    You mean it uses the type of the pointer?
    You told the compiler "this is a pointer to Base", and it was unable to find any reason to disbelieve you.

  15. #15
    The Dragon Reborn
    Join Date
    Nov 2009
    Location
    Dublin, Ireland
    Posts
    629
    Quote Originally Posted by whiteflags View Post
    I'm not sure what you mean -- I think you are talking about return types; which, in that case, you are right -- but virtual is not a type. It is a keyword.



    As the FAQ tried to explain, delete p is not necessarily resulting in the type of p's destructor being called (first). If you have a virtual destructor, a run-time check for the type will occur and result in the correct destructors being called, which makes the delete a well defined operation. If you depend on undefined behavior, then simply because something good happens on your machine and the result is good for you, doesn't mean that when I compile it I will get the same result.

    Let's take this code:

    Base *p = new Derived;
    delete p;

    Along with the code you originally posted, I get

    Constructor for Base class
    Constructor for Derived class
    Destructor for Base class

    No Derived destructor call for this object. So there's a lesson in undefined behavior today.
    hey! Cboard is back online!... so
    Quote Originally Posted by whiteflags View Post
    I'm not sure what you mean -- I think you are talking about return types; which, in that case, you are right -- but virtual is not a type. It is a keyword.



    As the FAQ tried to explain, delete p is not necessarily resulting in the type of p's destructor being called (first). If you have a virtual destructor, a run-time check for the type will occur and result in the correct destructors being called, which makes the delete a well defined operation. If you depend on undefined behavior, then simply because something good happens on your machine and the result is good for you, doesn't mean that when I compile it I will get the same result.

    Let's take this code:

    Base *p = new Derived;
    delete p;

    Along with the code you originally posted, I get

    Constructor for Base class
    Constructor for Derived class
    Destructor for Base class

    No Derived destructor call for this object. So there's a lesson in undefined behavior today.
    you're right..it only called destructor for Derived..when I used virtual, yeah and you were right i was referring to return types..

    I'm not sure why that happened..i know the behavior is undefined...but you knew the result you would get...
    normally, the derived destructor is called first. why skip to base's?

    i guess we don't have to use virtual for constructors since it is required for us to explicitly call it, if we have defined one..otherwise it does done for us.
    You ended that sentence with a preposition...Bastard!

Popular pages Recent additions subscribe to a feed