CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 29 of 29
  1. #16
    Join Date
    Sep 2005
    Location
    United States
    Posts
    799

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by John E
    Suppose you have a 3 class hierarchy - base.... derived1 (derived from base) and derived2 (derived from derived1). Should you put virtual functions in base and derived1 or is it only necessary in the base class?
    In general, the base class should contain the initial virtual function declarations and definitions.
    Perhaps pure virtual if it is an abstract class, in which case no definition is given.

    Then, each derived class should override those virtual functions which it inherits from the base so that polymorphism can be used.
    Please rate my post if you felt it was helpful

  2. #17
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by John E
    Just looking through the rest of the 3rd party code I can see that objects of this type are always being created using a string literal but I'll change the class to use std::string anyway. I'm confused by this comment from SuperKoko:-

    Here's what I always thought to be the received wisdom with regard to virtual d'tors (i.e. always make the base class d'tor virtual).
    The author of that article is a little confused. Essentially correct, but gives the wrong impression. As SuperKoko and Yves have said - you need a virtual destructor if there is any chance that you will attempt to call delete on a pointer to base that is actually pointing to derived. In a well-designed program, this will only be possible if the base class contains virtual functions, since you will only be holding a pointer to base in order make use of polymorphic behaviour.

    Note that an alternative to a public virtual destructor is a protected non-virtual destructor. This simply prevents you from deleting a derived through a pointer to base - you have to delete through a pointer to derived (or you could have a derived declared on the stack - a protected base dtor prevents attempt to call delete if you pass its address around).

    Quote Originally Posted by linked article
    There is one more point to be noted regarding virtual destructor. We can't declare pure virtual destructor. Even if a virtual destructor is declared as pure, it will have to implement an empty body (at least) for the destructor.


    Quote Originally Posted by dcjr84
    In general, the base class should contain the initial virtual function declarations and definitions.
    Perhaps pure virtual if it is an abstract class, in which case no definition is given.
    NO, no and thrice no! "Pure" says nothing about whether the function has a body or not. "Pure" only means that the function is virtual and that its declaration in the class definition includes "= 0". Nothing more. It does not imply that the function has no body. Admittedly, pure virtuals rarely do have bodies, but it is not implicit in the definition of a pure virtual function.

    The linked article is wrong - you can declare a pure virtual destructor, but you must give it a body.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  3. #18
    Join Date
    Sep 2005
    Location
    United States
    Posts
    799

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by Graham
    NO, no and thrice no! "Pure" says nothing about whether the function has a body or not. "Pure" only means that the function is virtual and that its declaration in the class definition includes "= 0". Nothing more. It does not imply that the function has no body. Admittedly, pure virtuals rarely do have bodies, but it is not implicit in the definition of a pure virtual function.
    I created an example to test this.

    In the first example, I try to define my pure virtual function in the base class.

    Code:
    #include <iostream>
    #include <string>
    #include <new>
    
    class Shape
    {
       public:
          Shape(){;}
          virtual void draw() = 0
          {std::cout << "Hello!" << std::endl;}
    
       private:
          std::string name;
    };
    
    class Circle : public Shape
    {
       public:
          Circle(){name = "circle";}
          virtual void draw()
          {std::cout << name << std::endl;}
    
       private:
          std::string name;
    };
    
    class Triangle : public Shape
    {
       public:
          Triangle(){name = "triangle";}
          virtual void draw()
          {std::cout << name << std::endl;}
    
       private:
          std::string name;
    };
    
    int main()
    {
    
       Shape* myShapeArray[ 2 ];
       
       myShapeArray[ 0 ] = new Circle();
       myShapeArray[ 1 ] = new Triangle();
    
       myShapeArray[ 0 ]->draw();
       myShapeArray[ 1 ]->draw();
    
       return 0;   
    
    }
    The code does not compile and gives the following error
    10 C:\Documents and Settings\dcjr84\My Documents\Untitled1.cpp pure-specifier on function-definition
    Now, in this example, I have the definition commented out.
    Everything works fine as it should....
    Code:
    #include <iostream>
    #include <string>
    #include <new>
    
    class Shape
    {
       public:
          Shape(){;}
          virtual void draw() = 0;
          //{std::cout << "Hello!" << std::endl;}
    
       private:
          std::string name;
    };
    
    class Circle : public Shape
    {
       public:
          Circle(){name = "circle";}
          virtual void draw()
          {std::cout << name << std::endl;}
    
       private:
          std::string name;
    };
    
    class Triangle : public Shape
    {
       public:
          Triangle(){name = "triangle";}
          virtual void draw()
          {std::cout << name << std::endl;}
    
       private:
          std::string name;
    };
    
    int main()
    {
    
       Shape* myShapeArray[ 2 ];
       
       myShapeArray[ 0 ] = new Circle();
       myShapeArray[ 1 ] = new Triangle();
    
       myShapeArray[ 0 ]->draw();
       myShapeArray[ 1 ]->draw();
    
       return 0;
    
    }
    The output is as expected
    circle
    triangle
    Care to explain this?

    From this example it would seem that a pure virtual function does in fact imply no definition, because my code will not compile if I try to give it one.
    Last edited by dcjr84; October 29th, 2006 at 09:53 AM.
    Please rate my post if you felt it was helpful

  4. #19
    Join Date
    Feb 2005
    Location
    Normandy in France
    Posts
    4,590

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by dcjr84
    From this example it would seem that a pure virtual function does imply no definition, because my code will not compile if I try to give it one.
    However, you're wrong.
    It's not possible to declare & define at the same time a pure virtual function (probably due to a parsing limitation).
    But if you define your function separately, it should work!
    Code:
    class Shape
    {
       public:
          Shape(){;}
          virtual void draw() = 0;
    
       private:
          std::string name;
    };
    void Shape::draw() {
    std::cout << "Hello!" << std::endl;
    }
    Note that, even if a definition is provided, calling a pure virtual function without explicit scope resolution, has undefined behavior.
    "inherit to be reused by code that uses the base class, not to reuse base class code", Sutter and Alexandrescu, C++ Coding Standards.
    Club of lovers of the C++ typecasts cute syntax: Only recorded member.

    Out of memory happens! Handle it properly!
    Say no to g_new()!

  5. #20
    Join Date
    Sep 2005
    Location
    United States
    Posts
    799

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by SuperKoko
    It's not possible to declare & define at the same time a pure virtual function (probably due to a parsing limitation).
    Aha!

    Indeed, when I define the pure virtual function separately, it compiles fine and works properly.

    I was wrong, my mistake
    Please rate my post if you felt it was helpful

  6. #21
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: Are these c'tors legal or dangerous?

    Apologies if I get a bit het up over this issue, but every single candidate I interview gets it wrong. Although it's rarely used, it is very useful. Basically, what you are saying by giving an implementation for a pure virtual function is "here is a default implementation for this function. If a derived class wishes to accept the default it must do so explicitly by overriding the function and calling the base class version". When you have a non-pure virtual function, the derived class can get the default action by accident. A pure with implementation eliminates the accidental inheritance of implementation.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  7. #22
    Join Date
    Jun 2002
    Location
    Moscow, Russia.
    Posts
    2,176

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by Graham
    Apologies if I get a bit het up over this issue, but every single candidate I interview gets it wrong. Although it's rarely used, it is very useful. Basically, what you are saying by giving an implementation for a pure virtual function is "here is a default implementation for this function. If a derived class wishes to accept the default it must do so explicitly by overriding the function and calling the base class version". When you have a non-pure virtual function, the derived class can get the default action by accident. A pure with implementation eliminates the accidental inheritance of implementation.
    Good point, but the same could be done with ordinary default implementation method (declared separately) plus pure virtual method. All without these arcane pure-virtual-with-implementation things. You don't need surprising language feature in order to do this. Especially if as you admit it's rarely used.
    "Programs must be written for people to read, and only incidentally for machines to execute."

  8. #23
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by RoboTact
    Good point, but the same could be done with ordinary default implementation method (declared separately) plus pure virtual method. All without these arcane pure-virtual-with-implementation things. You don't need surprising language feature in order to do this. Especially if as you admit it's rarely used.
    a.k.a. Template Pattern or Non-Virtual Interface. I prefer these mechanism as they are more likely to be used correctly from the derived class.

    Jeff

  9. #24
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by RoboTact
    Good point, but the same could be done with ordinary default implementation method (declared separately) plus pure virtual method. All without these arcane pure-virtual-with-implementation things. You don't need surprising language feature in order to do this. Especially if as you admit it's rarely used.
    Maybe it's because our clocks have gone back, but I don't see how they're the same. If you provide an unimplemented pure virtual, then the derived class has to provide an implementation of its action. What I'm saying is that the derived implementation consists solely of a call to the base function:
    Code:
    class foo
    {
    public:
    	virtual void f() = 0;
    };
    
    void foo::f()
    {
    	// implementation
    }
    
    class bar : public foo
    {
    public:
    	virtual void f()
    	{
    		foo:f();
    	}
    };
    Are you suggesting something like:
    Code:
    class foo
    {
    public:
    	virtual void f() = 0; // no implementation
    
    protected:
    	void f_default()
    	{
    		// default implementation
    	}
    };
    
    class bar : public foo
    {
    public:
    	virtual void f()
    	{
    		foo::f_default();
    	}
    };
    If so, I don't see where the gain is.

    And pure-with-implementation is not arcane. It's simply understanding what a pure virtual function actually is - it's a virtual function that must be overridden, nothing more, nothing less.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  10. #25
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582

    Re: Are these c'tors legal or dangerous?

    Code:
    class foo
    {
    public:
    	void f()
    	{
    		// default implementation
    		...
    		handleF();
    	}
      
    
    protected:
    	// alternatively, could be pure virtual
    	virtual void handleF()
    	{
    	}
    };
    
    class bar : public foo
    {
    protected:
    	virtual void handleF()
    	{
    		// derived implementation
    	}
    };

    Jeff

  11. #26
    Join Date
    Feb 2005
    Location
    Normandy in France
    Posts
    4,590

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by jfaust
    Code:
    class foo
    {
    public:
    	void f()
    	{
    		// default implementation
    		...
    		handleF();
    	}
      
    
    protected:
    	// alternatively, could be pure virtual
    	virtual void handleF()
    	{
    	}
    };
    
    class bar : public foo
    {
    protected:
    	virtual void handleF()
    	{
    		// derived implementation
    	}
    };

    Jeff
    It isn't equivalent to a default implementation, since the code around in f() is executed even if handleF() is overriden.
    Yes, it is often wishable and useful, but it doesn't solve the same problem.
    "inherit to be reused by code that uses the base class, not to reuse base class code", Sutter and Alexandrescu, C++ Coding Standards.
    Club of lovers of the C++ typecasts cute syntax: Only recorded member.

    Out of memory happens! Handle it properly!
    Say no to g_new()!

  12. #27
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582

    Re: Are these c'tors legal or dangerous?

    Quote Originally Posted by SuperKoko
    It isn't equivalent to a default implementation, since the code around in f() is executed even if handleF() is overriden.
    Yes, it is often wishable and useful, but it doesn't solve the same problem.
    Not precisely the same problem, but there is an overwhelming amount of overlap. In the cases where you don't want to execute the default code, you could modify my example to handle the same problem:

    Code:
    class foo
    {
    public:
    	void f()
    	{
    		assert(preconditions);
    		defaultF();
    		handleF();
    		assert(postconditions);
    	}
      
    
    protected:
    	virtual void defaultF()
    	{
    		// default implementation
    	}
    
    	// alternatively, could be pure virtual
    	virtual void handleF()
    	{
    	}
    };
    
    class bar : public foo
    {
    protected:
    	virtual void handleF()
    	{
    		// derived implementation
    	}
    };
    This would be safer for the cases where most derived classes do want the default, but still leave room for others to prevent the default.

    Note that I'm not arguing against pure virtuals with implementations. This is just a technique that I use in similar circumstances. One reason I really like this mechanism is the assertions I've put in the non-virtual method.

    Jeff

  13. #28
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: Are these c'tors legal or dangerous?

    jfaust: yes, your example is one that I use myself, probably more often than I use PVI (pure-virtual-with-implementation). However, I agree with SuperKoko that it does not solve the same problem.

    Template pattern gives you a mandatory implementation, with an overridable part.

    POV (plain ol' virtual) gives you an optional implementation that can be inherited accidentally.

    PVI gives the same as POV, but without the "accidental" part.

    POV and PVI are subsets of template pattern, not synonyms, which is why there is so much overlap, as you point out.

    Indeed, Template pattern is, I would guess, the primary place for using PVI - you make the variable parts of the template PVI functions, so that a derived class has to explicitly accept the default processing at each of those points.
    Last edited by Graham; October 30th, 2006 at 04:47 AM.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  14. #29
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: Are these c'tors legal or dangerous?

    The problems I sometimes have with virtual functions is that I get the override prototype slightly wrong (maybe missing a const or putting one in where there shouldn't be one, or a slightly different name or parameter list) and then I end up not with an override at all but with a totally different function that is in reality never invoked.

    A good reason, of course, to use pure virtual functions even when they have a default implementation. Then these errors would be caught at compile time.

    Yves: you are not quite correct. There is a way to finalise a class in C++ - give it all private constructors and a friend or static method to create one. Then there is no way to derive from the class.

    What is not possible is to finalise a single virtual method within the class. If you really do want to do that (you want to particular implementation where it is different functions that are overloaded) then you can split the class in two, have a class with private constructors but with a "has-a" relationship on your new interface so that others will derive from your new interface and pass a pointer (or smart-pointer) as a parameter to your constructor.

Page 2 of 2 FirstFirst 12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured