LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-09-2011, 05:16 AM   #1
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
C++: Does it make sense to *define* the pure virtual functions in the *abstract base* class itself?


By defining I mean writing the function body.

The benefit of defining common virtual functions in the base class is that we don't have to redefine them in the derived classes then.

Even if we define pure virtual functions in the base class itself, we'll still have to define them in the derived classes too.

Code:
#include <iostream>
using namespace std;

class speciesFamily
{
    public:
        virtual void numberOfLegs () = 0;
};

void speciesFamily :: numberOfLegs ()
{
    cout << "\nFour";
}

class catFamily : public speciesFamily
{
    public:
        void numberOfLegs ()
        {
            speciesFamily :: numberOfLegs ();
        }
};
This may look fancy for sure, but are there any real situations when it is beneficial to define a pure virtual function in the base class itself?

Last edited by Aquarius_Girl; 11-21-2011 at 06:45 PM. Reason: People misread the post
 
Old 11-09-2011, 05:54 AM   #2
neonsignal
Senior Member
 
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
Blog Entries: 54

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
There are two possible purposes for providing member function bodies in a parent class; the first is to provide a default behaviour, and the second is to provide shared functionality to derived classes.

Since an abstract class does not need default behaviour, then only the second of these applies in this case. In other words, the pure virtual member body is functionality that may be useful to derived classes.
 
Old 11-09-2011, 05:57 AM   #3
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
By "shared functionality" do you mean that derived class can
call it if and when it likes?

If yes, then doesn't it make more sense to simply remove the
"abstract" feature and let the class breath (allow to create
objects)?
 
Old 11-09-2011, 06:16 AM   #4
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by Anisha Kaul View Post
By "shared functionality" do you mean that derived class can
call it if and when it likes?

If yes, then doesn't it make more sense to simply remove the
"abstract" feature and let the class breath (allow to create
objects)?
Go back to the classic example of defining shapes: triangle, circle, polygon, rectangle, and a square (a special rectangle). For each of these shapes, you could compute the perimeter of the shape or even the area occupied by the shape. The means for computing these attributes will vary between the various shapes, thus it would not be practical for a base-class to define a "default" implementation of the functions needed to compute these values.

Thus, one can view "shape" as an abstract entity which defines the methods for perimeter() and area(). The aforementioned shapes would derive from this base class, and implement their respective methods for computing perimeter() and area(). So for example:
Code:
class Shape
{
public:
   /// define pure-virtual methods that derived shapes must implement
   virtual double perimeter() const = 0;
   virtual double area() const = 0;
};

class Rectangle : public Shape
{
public:
   Rectangle(const double w, const double l)
      : width(w), length(l)
   {
   }

   virtual ~Rectangle() {}

   // define implementation for abstract methods declared in base-class

   double perimeter() const
   {
      return 2 * (width + length);
   }

   double area() const
   {
      return width * length;
   }

private:
   double width;
   double length;
};

Last edited by dwhitney67; 11-09-2011 at 06:18 AM.
 
1 members found this post helpful.
Old 11-09-2011, 06:30 AM   #5
SigTerm
Member
 
Registered: Dec 2009
Distribution: Slackware 12.2
Posts: 379

Rep: Reputation: 234Reputation: 234Reputation: 234
Quote:
Originally Posted by Anisha Kaul View Post
C++: Does it make any sense to define the *pure* virtual functions in the base class itself?
Yes, it does. See COM interface declarations for windows platform, "interface" pattern, "command" pattern and "visitor" pattern. It is an incredibly useful language feature, that simplifies creation of plugins, allows you to replace callbacks with classes, and so on. Also your base abstract class may implement partial algorithm that requires data provided by children of that class.

Code:
#include <iostream>
using namespace std;

class speciesFamily
{
    public:
        virtual void numberOfLegs () = 0;
};
This is not useful.

Here's real-life usage:
Code:
class CachedValue{
private:
	mutable bool valueCalculated;
	mutable float lastValue;
protected:
	void update(){
		valueCalculated = false;
	}
	
	virtual float calculateValue() const = 0;

	float getValue() const{
		if (!valueCalculated){
			lastValue = calculateValue();
			valueCalculated = true;
		}
		return lastValue;
	}

	CachedValue()
	:valueCalculated(false), lastValue(0.0f){
	}

	virtual ~CachedValue(){
	}
};

Last edited by SigTerm; 11-09-2011 at 07:08 AM.
 
Old 11-09-2011, 07:36 AM   #6
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
Quote:
Originally Posted by dwhitney67 View Post
Thus, one can view "shape" as an abstract entity which defines the methods for perimeter() and area(). The aforementioned shapes would derive from this base class, and implement their respective methods for computing perimeter() and area(). So for example:
Actually my question was about *defining* the pure virtual
function in the *abstract base* class. I don't see anything
like that in your example.
 
Old 11-09-2011, 09:00 AM   #7
SigTerm
Member
 
Registered: Dec 2009
Distribution: Slackware 12.2
Posts: 379

Rep: Reputation: 234Reputation: 234Reputation: 234
Quote:
Originally Posted by Anisha Kaul View Post
Actually my question was about *defining* the pure virtual
function in the *abstract base* class. I don't see anything
like that in your example.
I misread your question. You might want to rename question to something like that "Function body for pure virtual methods?"

SO has similar question - with answers. Also there are those examples.
As far as I can tell, the most useful usages are:
  1. Virtual destructor. If class has nothing except destructor, you can make it abstract by making destructor pure virtual. However, destructor needs a body in order to work.
  2. "force conscious acceptance of default behavior". You provide body but derived class must explicitly call it.
  3. "prevent creation of class instances". I.e. you provide function body, but prevent creation of class instance by making it abstract. You could do same thing by making constructor protected, though.
  4. To provide default function body for diagnostical purposes - in case you somehow end up calling pure virtual function, it could print/log a diagnostical message somewhere.

In my opinion, you may run into pure virtual destructor eventually, and it is probably the most common use of this language feature.
Code:
class A{
public:
	virtual ~A() = 0;
};

A::~A(){}//<-- comment this out and see what happens


class B: public A{
};

int main(int argc, char** argv){
	B b;
	return 0;
}

Last edited by SigTerm; 11-09-2011 at 09:24 AM.
 
1 members found this post helpful.
Old 11-09-2011, 11:09 AM   #8
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 11,222

Rep: Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320
EDIT: misread the question.

Last edited by dugan; 11-09-2011 at 11:10 AM.
 
Old 11-09-2011, 11:34 AM   #9
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3939Reputation: 3939Reputation: 3939Reputation: 3939Reputation: 3939Reputation: 3939Reputation: 3939Reputation: 3939Reputation: 3939Reputation: 3939Reputation: 3939
It just takes careful planning ... to go "far enough to be useful" in abstracting your design, without "building a hole for your project to fall into."

If you define a "pure virtual function in an abstract class," then what you're saying is that every descendent class [i]must[/u] define an implementation for this function. The compiler will obligingly prevent you from doing otherwise.

Some designers argue that you should "implement a do-nothing function, designed to be overridden, that blows-up if it is actually called." The problem here being that the compiler can't prevent you from writing code that calls the bomb, thus turning what could be a compile-time error into a run-time error.

In my humble, there is no bright-line rule here. It's your project, therefore your decision, just try to think ahead as far as you can. If you can reasonably think of a case where this-or-that function would not properly be implemented by a descendent class, then you probably need to re-consider your rules.
 
Old 11-09-2011, 11:37 AM   #10
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by Anisha Kaul View Post
Actually my question was about *defining* the pure virtual
function in the *abstract base* class. I don't see anything
like that in your example.
You are correct; what would be the purpose of declaring a function as pure-virtual if the intent is to define a default implementation? If the plan is to provide a default implementation, then the function should be declared as virtual (not pure-virtual). It would be nice if the compiler would issue a warning if/when one defines a function that was previously declared as a pure-virtual function.

Last edited by dwhitney67; 11-09-2011 at 11:38 AM.
 
Old 11-09-2011, 11:38 AM   #11
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
Quote:
Originally Posted by sundialsvcs View Post
If you define a "pure virtual function in an abstract class," then what you're saying is that every descendent class [i]must[/u] define an implementation for this function.
Declaring is enough (in the *abstract base* class), definition is not necessary, AFAIK.
 
Old 11-09-2011, 12:21 PM   #12
SigTerm
Member
 
Registered: Dec 2009
Distribution: Slackware 12.2
Posts: 379

Rep: Reputation: 234Reputation: 234Reputation: 234
Quote:
Originally Posted by Anisha Kaul View Post
Declaring is enough (in the *abstract base* class), definition is not necessary, AFAIK.
I gave you "pure virtual destructor example" in post #7. Have you tried compiling with "A::~A(){}" commented out as was suggested in the comment? It looks like you haven't. Well, you should have given it a try. Compiling it without "A::~A(){}" will create unresolved external error on both g++/cl.exe, and it will not be possible to create instance of any class that inherits from "A". So "only declaring" is not always enough.

As for the rest of the issue (I.e. "pure virtual function (that is not a destructor) with a body") I think it is a matter of taste. It is possible that there's a scenario (aside from pure virtual destructor) when this feature is absolutely necessary.

Last edited by SigTerm; 11-09-2011 at 12:27 PM.
 
1 members found this post helpful.
Old 11-21-2011, 05:11 AM   #13
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
Quote:
Originally Posted by SigTerm View Post
I misread your question.
What did you think the question was? That'll help me in connecting to
your previous answer.

Quote:
Originally Posted by SigTerm View Post
SO has similar question - with answers. Also there are those examples.
Very helpful links. I'll look around more carefully next time before posting.
Pure virtual destructor was a new thing, although I couldn't find any more
uses of it.

Quote:
Originally Posted by SigTerm View Post
In my opinion, you may run into pure virtual destructor eventually, and it is probably the most common use of this language feature.
You meant the most common use of the pure virtual destructor is to make
a class abstract without a dummy pure virtual function?

P.S.
That day I didn't read your detailed replies since didn't have enough
time. Thanks for your great help.
 
Old 11-21-2011, 01:19 PM   #14
SigTerm
Member
 
Registered: Dec 2009
Distribution: Slackware 12.2
Posts: 379

Rep: Reputation: 234Reputation: 234Reputation: 234
Quote:
Originally Posted by Anisha Kaul View Post
What did you think the question was?
"what is the purpose/use of pure virtual methods in base class". "Define" does not obviously mean "function with a body", and I often confuse define/declare. Looks like few other people misread your question in similar fashion.

Quote:
Originally Posted by Anisha Kaul View Post
You meant the most common use of the pure virtual destructor is to make
a class abstract without a dummy pure virtual function?
I'm not sure about "most common use", but it is the most obvious possible use of virtual abstract method with a body. Few guys on SO claim that it is "the most common", but I don't remember actually seeing such pattern in live code, so I'm not sure. Maybe i haven't noticed it, though.
 
Old 11-21-2011, 06:51 PM   #15
Aquarius_Girl
Senior Member
 
Registered: Dec 2008
Posts: 4,731

Original Poster
Blog Entries: 29

Rep: Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940Reputation: 940
Quote:
Originally Posted by SigTerm View Post
"Define" does not obviously mean "function with a body"
*Ahem*
and I thought "C++", "define", and "function" together will
be obvious enough. :-)

Anyway, since it is now over 7 days, so modifying title won't
reflect on the main page. I have edited the OP.

P.S. Thanks for following up.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
HELP:: Can I have virtual functions in derived class?? < Are they restricted to Base> caruna Programming 3 12-22-2009 10:17 AM
Pure virtual functions Doubt naveenisback Programming 1 10-30-2009 03:22 AM
need proprietary alternative to GPL-licensed functions in linux/drivers/base/class.c lightdee Linux - Kernel 2 09-05-2009 01:20 PM
casting void* to an abstract class qwijibow Programming 3 12-23-2006 08:43 PM
c++ Abstract Base Classes exodist Programming 1 06-11-2005 06:05 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:57 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration