Thread: precondition and post condition check

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    1,579

    precondition and post condition check

    Hello everyone,


    I am looking for a good sample about how to implement C++ pre-condition and post condition check, but can not find a good sample code. Do you have any referred ones? :-)

    Since I can not find, I wrote the patterns in two ways, I am not sure which is correct and if both are not correct, how to implement this pattern?

    Sample code 1,

    Code:
    #define MAX 1024
    
    class Base
    {
    public:
    	void foo(int i)
    	{
    	if (i > MAX)
    	{
    		// error handling
    	}
    	else
    	{
    		do_foo(i);
    	}
    }
    
    private:
    	virtual void do_foo(int i) = 0;
    };
    
    class Derived : public Base
    {
    private:
    	virtual void do_foo(int i)
    	{
    	// i is never > MAX here
    	}
    };
    
    int main()
    {
    	Derived d;
    	d.foo (1000);
    
    	return 0;
    }
    Sample 2,

    Code:
    #define MAX 1024
    
    class Base
    {
    public:
    	void foo(int i)
    	{
    	if (i > MAX)
    	{
    		// error handling
    	}
    	else
    	{
    		do_foo(i);
    	}
    }
    
    private:
    	virtual void do_foo(int i) = 0;
    };
    
    class Derived : public Base
    {
    public:
    	virtual void do_foo(int i)
    	{
    		foo (i);
    		// i is never > MAX here
    	}
    };
    
    int main()
    {
    	Derived d;
    	d.do_foo (1000);
    
    	return 0;
    }

    thanks in advance,
    George

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You so need a book.

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi Bubba,


    I have some books at hand, but can not find out. So, I do some practices and ask question here. Any ideas to my original question? :-)

    Quote Originally Posted by Bubba View Post
    You so need a book.

    regards,
    George

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    The second example more properly:
    Code:
    #define MAX 1024
    
    class Base
    {
    public:
    	void foo(int i)
    	{
    	if (i > MAX)
    	{
    		// error handling
    	}
    	else
    	{
    		do_foo(i);
    	}
    }
    
    private:
    	virtual void do_foo(int i) = 0;
    };
    
    class Derived : public Base
    {
    public:
    	virtual void do_foo(int i)
    	{
    		foo (i);
    		// i is never > MAX here
    		//which doesn't matter since you never get here anyway
    	}
    };
    
    int main()
    {
    	Derived d;
    	d.do_foo (1000);
    
    	return 0;
    }
    You seem to do a lot of reading, but you don't learn much if you don't write, compile and run a lot of programs. What stopped you from finding out that the second version is bugged?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Thanks anon,


    What is the bug in sample 2? Do you mean the return value of foo (i) is not checked in do_foo functon of class Derived?

    Quote Originally Posted by anon View Post
    The second example more properly:
    Code:
    #define MAX 1024
    
    class Base
    {
    public:
    	void foo(int i)
    	{
    	if (i > MAX)
    	{
    		// error handling
    	}
    	else
    	{
    		do_foo(i);
    	}
    }
    
    private:
    	virtual void do_foo(int i) = 0;
    };
    
    class Derived : public Base
    {
    public:
    	virtual void do_foo(int i)
    	{
    		foo (i);
    		// i is never > MAX here
    		//which doesn't matter since you never get here anyway
    	}
    };
    
    int main()
    {
    	Derived d;
    	d.do_foo (1000);
    
    	return 0;
    }
    You seem to do a lot of reading, but you don't learn much if you don't write, compile and run a lot of programs. What stopped you from finding out that the second version is bugged?

    regards,
    George

  6. #6
    Registered User Mortissus's Avatar
    Join Date
    Dec 2004
    Location
    Brazil, Porto Alegre
    Posts
    152
    Isn't because do_foo call foo that calls do_foo again (and so forever)???
    Did you run this code?

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Sorry, Mortissus. My bad. :-)


    Which approach (1) or (2) in my original post do you think is the correct implementation of pre- and post- condition pattern?

    If neither are correct, could you let me know what is the correct implementation of pre- and post- pattern please?

    Quote Originally Posted by Mortissus View Post
    Isn't because do_foo call foo that calls do_foo again (and so forever)???
    Did you run this code?

    regards,
    George

  8. #8
    Registered User Mortissus's Avatar
    Join Date
    Dec 2004
    Location
    Brazil, Porto Alegre
    Posts
    152
    What is the difference between them? The only thing I spot is the foo() being called inside do_foo(), which we agreed is an error.

  9. #9
    The larch
    Join Date
    May 2006
    Posts
    3,573
    It seems that the difference is that in one case the virtual function is accessed through a non-virtual function in the base. This way the precondition check would be done automatically for all inherited classes (although it seems possible to override the non-virtual function in a derived class and bypass the check if derived class is not used polymorphically).

    In the second case, probably, the base class would provide a checking function and it would be up to the derived class to decide whether they want to use that checking method.

    The use cases seem to be a bit different.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  10. #10
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Neither of those offerings provide an "implementation" of a precondition or a postcondition. Not that "implementation" is even the correct word.

    A precondition and a postcondition just form part of the contract of an interface. The precondition tells the programmer, and not the compiler, what argument values are valid. The postcondition tells the programmer, and not the compiler, what the implementation of the interface will accomplish but not how it is accomplished.

    Both the precondition and the postcondition should appear in the documentation, but that is all. It is occasionally useful, primarily during debugging, to give them a source level counterpart, but beyond that they have no business being in implementation source.

    During debugging of source using the interface it can be useful to have a source level constraint equivalent to the precondition. If you desire such a constraint it should be wrapped in an 'assert'.

    During debugging of the implementation it can be useful to have a source level constraint equivalent to the postcondition. If you desire such a constraint it should be wrapped in something very like 'assert'.

    It could be argued as a matter of personal taste, but in general any inheritance of interface/implementation naturally inherits any preconditions and postconditions. For this reason any source level constraint written as a counterpart to a precondition or postcondition should be written as part of a public/protected interface. In this way classes that inherit the interface can override the implementation and optionally override, inherit, or add to the existing implementation of such constraints.

    Soma
    Last edited by phantomotap; 03-18-2008 at 10:11 AM. Reason: Clarity.

  11. #11
    Registered User
    Join Date
    May 2006
    Posts
    1,579
    Hi Mortissus,


    Please refer to anon's reply #9 for details about the differences.

    Quote Originally Posted by Mortissus View Post
    What is the difference between them? The only thing I spot is the foo() being called inside do_foo(), which we agreed is an error.

    Thanks anon,


    Generally, I agree with you. A small mistake in your below reply, we can only override a virtual function, we can not override a non-virtual function.

    Quote Originally Posted by anon View Post
    This way the precondition check would be done automatically for all inherited classes (although it seems possible to override the non-virtual function in a derived class and bypass the check if derived class is not used polymorphically).

    Thanks Soma,


    I generally agree with your points. Do you have any formal learning materials or documents about pre- and post- pattern? I have made some search, but failed to find.

    Quote Originally Posted by phantomotap View Post
    Neither of those offerings provide an "implementation" of a precondition or a postcondition. Not that "implementation" is even the correct word.

    A precondition and a postcondition just form part of the contract of an interface. The precondition tells the programmer, and not the compiler, what argument values are valid. The postcondition tells the programmer, and not the compiler, what the implementation of the interface will accomplish but not how it is accomplished.

    Both the precondition and the postcondition should appear in the documentation, but that is all. It is occasionally useful, primarily during debugging, to give them a source level counterpart, but beyond that they have no business being in implementation source.

    During debugging of source using the interface it can be useful to have a source level constraint equivalent to the precondition. If you desire such a constraint it should be wrapped in an 'assert'.

    During debugging of the implementation it can be useful to have a source level constraint equivalent to the postcondition. If you desire such a constraint it should be wrapped in something very like 'assert'.

    It could be argued as a matter of personal taste, but in general any inheritance of interface/implementation naturally inherits any preconditions and postconditions. For this reason any source level constraint written as a counterpart to a precondition or postcondition should be written as part of a public/protected interface. In this way classes that inherit the interface can override the implementation and optionally override, inherit, or add to the existing implementation of such constraints.

    Soma

    regards,
    George

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Constructive Feed Back (Java Program)
    By xddxogm3 in forum Tech Board
    Replies: 12
    Last Post: 10-10-2004, 03:41 AM