Thread: Why constructor can not call pure virtual functions?

  1. #1
    Registered User
    Join Date
    Apr 2007
    Posts
    284

    Why constructor can not call pure virtual functions?

    ================================================== =====

    UPDATE:
    I think my original post was a little misleading. Here is what I indeed want to know:
    When I use this->foo() in the following code, it works, even for a pure virtual function;

    Code:
    class A{                                                                                                                                                                     
    public:                                                                                                                                                                      
        A(){                                                                                                                                                                     
            this->foo();
        }                                                                                                                                                                        
        ~A(){}                                                                                                                                                                   
        virtual void foo()=0;                                                                                                                                                    
    };                                                                                                                                                                           
                                                                                                                                                                                 
    void A::foo(){        cout<<"Class A"<<endl; }                                                                                                                             
                                                                                                                                                                                 
    class B: public A{                                                                                                                                                           
    public:                                                                                                                                                                      
        B(){                                                                                                                                                                     
            this->foo();
        }                                                                                                                                                                        
        ~B(){}                                                                                                                                                                   
        void foo(){                                                                                                                                                              
            cout<<"Class B"<<endl;                                                                                                                                               
        }                                                                                                                                                                        
    };                                                                                                                                                                           
                                                                                                                                                                                 
    int main()                                                                                                                                                                   
    {                                                                                                                                                                            
        B obj;                                                                                                                                                                   
        return 0;                                                                                                                                                                
    }

    But when I use foo() instead, I got the compile-time error

    Code:
    class A{                                                                                                                                                                     
    public:                                                                                                                                                                      
        A(){                                                                                                                                                                     
            foo();
        }                                                                                                                                                                        
        ~A(){}                                                                                                                                                                   
        virtual void foo()=0;                                                                                                                                                    
    };                                                                                                                                                                           
                                                                                                                                                                                 
    void A::foo(){        cout<<"Class A"<<endl; }                                                                                                                             
                                                                                                                                                                                 
    class B: public A{                                                                                                                                                           
    public:                                                                                                                                                                      
        B(){
            foo();                                                                                                                                                             
        }                                                                                                                                                                        
        ~B(){}                                                                                                                                                                   
        void foo(){                                                                                                                                                              
            cout<<"Class B"<<endl;                                                                                                                                               
        }                                                                                                                                                                        
    };                                                                                                                                                                           
                                                                                                                                                                                 
    int main()                                                                                                                                                                   
    {                                                                                                                                                                            
        B obj;                                                                                                                                                                   
        return 0;                                                                                                                                                                
    }
    So I wonder what's the difference between this->foo() and foo() in my code?

    ================================================== ========
    Original Post:

    Why constructor can not call a pure virtual function, even if it's defined?
    Another question is what's the difference between this->foo() and foo() ?
    In my opinion they are the same.

    Code:
    class A{                                                                                                                                                                     
    public:                                                                                                                                                                      
        A(){                                                                                                                                                                     
            //this->foo();                                                                                                                                                       
            foo();                                                                                                                                                               
        }                                                                                                                                                                        
        ~A(){}                                                                                                                                                                   
        virtual void foo()=0;                                                                                                                                                    
    };                                                                                                                                                                           
                                                                                                                                                                                 
    void A::foo(){  cout<<"Class A"<<endl; }                                                                                                                                     
                                                                                                                                                                                 
    class B: public A{                                                                                                                                                           
    public:                                                                                                                                                                      
        B(){                                                                                                                                                                     
            //this->foo();                                                                                                                                                       
            foo();                                                                                                                                                               
        }                                                                                                                                                                        
        ~B(){}                                                                                                                                                                   
        virtual void foo(){                                                                                                                                                      
            cout<<"Class B"<<endl;                                                                                                                                               
        }                                                                                                                                                                        
    };                                                                                                                                                                           
                                                                                                                                                                                 
    int main()                                                                                                                                                                   
    {                                                                                                                                                                            
        B obj;                                                                                                                                                                   
        return 0;                                                                                                                                                                
    }
    Last edited by meili100; 03-07-2008 at 01:26 PM.

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Another programmer can come along and create class C : public B and implement foo using member variables of class C. If you call foo from inside the class B constructor, then because it is virtual you would want the class C implementation to be called. But then that would be using member variables that haven't been constructed yet because the C constructor isn't called until after the B constructor finishes.

    >> what's the difference between this->foo() and foo()
    There is rarely any difference. There was a thread recently where one example of a case where this->foo() worked but foo() didn't, but for the most part they are the same and you might as well just use foo().

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Why constructor can not call a pure virtual function, even if it's defined?
    I believe you have to qualify pure virtual functions in order to call them:
    Code:
    A(){
        A::foo();
    }
    That said, read this related FAQ: When my base class's constructor calls a virtual function on its this object, why doesn't my derived class's override of that virtual function get invoked?

    Another question is what's the difference between this->foo() and foo() ?
    In my opinion they are the same.
    Generally, yes. An exception has to do with templates, where if foo is a non-dependent name, this->foo() will cause the correct name lookup.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Apr 2007
    Posts
    284
    Thanks all. Where is the thread talking about one example of a case where this->foo() worked but foo() didn't?

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I tried, but the volume of posts in this forum is so high that my searches were in vain. Perhaps I searched with the wrong keywords. Anyway, you can read this related FAQ: Why am I getting errors when my template-derived-class uses a member it inherits from its template-base-class?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Apr 2007
    Posts
    284
    Thanks again. I think my original post was a little misleading. Here is what I indeed want to know:
    When I use this->foo() in the following code, it works, even for a pure virtual function;

    Code:
    class A{                                                                                                                                                                     
    public:                                                                                                                                                                      
        A(){                                                                                                                                                                     
            this->foo();
        }                                                                                                                                                                        
        ~A(){}                                                                                                                                                                   
        virtual void foo()=0;                                                                                                                                                    
    };                                                                                                                                                                           
                                                                                                                                                                                 
    void A::foo(){        cout<<"Class A"<<endl; }                                                                                                                             
                                                                                                                                                                                 
    class B: public A{                                                                                                                                                           
    public:                                                                                                                                                                      
        B(){                                                                                                                                                                     
            this->foo();
        }                                                                                                                                                                        
        ~B(){}                                                                                                                                                                   
        void foo(){                                                                                                                                                              
            cout<<"Class B"<<endl;                                                                                                                                               
        }                                                                                                                                                                        
    };                                                                                                                                                                           
                                                                                                                                                                                 
    int main()                                                                                                                                                                   
    {                                                                                                                                                                            
        B obj;                                                                                                                                                                   
        return 0;                                                                                                                                                                
    }

    But when I use foo() instead, I got the compile-time error

    Code:
    class A{                                                                                                                                                                     
    public:                                                                                                                                                                      
        A(){                                                                                                                                                                     
            foo();
        }                                                                                                                                                                        
        ~A(){}                                                                                                                                                                   
        virtual void foo()=0;                                                                                                                                                    
    };                                                                                                                                                                           
                                                                                                                                                                                 
    void A::foo(){        cout<<"Class A"<<endl; }                                                                                                                             
                                                                                                                                                                                 
    class B: public A{                                                                                                                                                           
    public:                                                                                                                                                                      
        B(){
            foo();                                                                                                                                                             
        }                                                                                                                                                                        
        ~B(){}                                                                                                                                                                   
        void foo(){                                                                                                                                                              
            cout<<"Class B"<<endl;                                                                                                                                               
        }                                                                                                                                                                        
    };                                                                                                                                                                           
                                                                                                                                                                                 
    int main()                                                                                                                                                                   
    {                                                                                                                                                                            
        B obj;                                                                                                                                                                   
        return 0;                                                                                                                                                                
    }
    So I wonder what's the difference between this->foo() and foo() in my code?
    Last edited by meili100; 03-07-2008 at 01:22 PM.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    When I use this->foo() in the following code, it works, even for a pure virtual function;
    I am not sure what the standard says, but I believe this is the same case as qualifying the pure virtual function call. Consider: it does not normally make sense to call a pure virtual function itself. One might appear to call it, but typically expect that its override would be called.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by meili100 View Post
    Thanks again. I think my original post was a little misleading. Here is what I indeed want to know:
    When I use this->foo() in the following code, it works, even for a pure virtual function;

    But when I use foo() instead, I got the compile-time error

    So I wonder what's the difference between this->foo() and foo() in my code?
    I get no compile error with foo() or this->foo() in either A or B, with VS2005 Express. Also, the code performed as expected.

    I suspect you're running an old compiler.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I get no compile error with foo() or this->foo() in either A or B, with VS2005 Express. Also, the code performed as expected.

    I suspect you're running an old compiler.
    The MinGW port of g++ 3.4.5 reports an error. The Comeau online compiler reports a warning. Personally, I think a warning is more proper since an implementation was provided.

    However, to settle this, the C++ Standard section 10.4 states:
    Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Yes; calling a pure virtual function from a constructor, acting on the object being constructed, yields undefined behaviour. A compiler error or warning is not required, but I would agree a warning is appropriate.

    Calling a non-abstract (for some reason calling it "impure" seems more appropriate in this context) virtual function in a constructor for class A always statically calls A::foo(). Practically, I would guess the compiler that allows this->foo() to compile is exercising that rule. Since the actual result is undefined, that compiler is not actually incorrect.

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Obligatory counter-example: GCC 4.2 tells me this:
    Code:
    g++     pure.cpp   -o pure
    /tmp/ccWd2q3c.o: In function `foo::foo()':
    pure.cpp:(.text._ZN3fooC2Ev[foo::foo()]+0x1d): undefined reference to `foo::beep()'
    for:
    Code:
    #include <iostream>
    
    class foo
    {
    public:
      foo() { this->beep(); }
      virtual ~foo() {}
      virtual void beep() = 0;
    };
    
    class bar : public foo
    {
    public:
      bar() {}
      virtual void beep() { std::cout << "beep\n"; }
    };
    
    int main()
    {
      bar b;
    }
    I get the same error message and a warning if I remove the explicit this.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    CornedBee, you forgot to implement foo::beep(). That would explain the "undefined reference to `foo::beep()'".
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Apr 2007
    Posts
    284
    Thanks all.
    My compiler is g++ (GCC) 3.3.5 (Debian 1:3.3.5-8)

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It's pure virtual. Why would I implement it?

    (Yeah, I know there are situations. But still ...)
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    It's pure virtual. Why would I implement it?
    To keep in line with meili100's question. If not, your "obligatory counter-example" is not a counter-example at all, but a slightly different example that thus results in a different set of compiler errors/warnings.

    EDIT:
    Then again, your counter-example is definitely not a counter-example since grumpy mused that "the compiler that allows this->foo() to compile is exercising that rule", but you got a linker error, not a compiler error.
    Last edited by laserlight; 03-07-2008 at 04:27 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 10-28-2009, 09:25 AM
  2. inheritance & virtual functions
    By xagiber in forum C++ Programming
    Replies: 3
    Last Post: 02-11-2002, 12:10 PM
  3. C++ XML Class
    By edwardtisdale in forum C++ Programming
    Replies: 0
    Last Post: 12-10-2001, 11:14 PM
  4. virtual or pure virtual
    By Unregistered in forum C++ Programming
    Replies: 1
    Last Post: 12-01-2001, 07:19 PM
  5. Exporting Object Hierarchies from a DLL
    By andy668 in forum C++ Programming
    Replies: 0
    Last Post: 10-20-2001, 01:26 PM