473,721 Members | 2,133 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

questions about virtual functions and abstract classes

Hello,

If I have a class that has virtual but non-pure declarations, like

class A{
virtual void f();
};

Then is A still an abstract class? Do I have to have "virtual void
f() = 0;" instead? I think declaring a function as "=0" is the same
as not giving its definition, is this right?

In addition, if I have a virtual destructor for an abstract class A,
then why do I still have to define it? For example, if I have

class B{
virtual ~B();
virtual void f() = 0;
};

Then my compiler still asks me to define ~B(). However, I will never
create an object of type B!

Additionally, I don't think I can declare virtual constructor, but it
seems I can't make a pure constructor like

class C{
C() = 0;
virtual void f()=0;
};

Again, if I never make an object of type C, why am I not allowed to
declare the constructor pure?

Moreover, is there any function or operator that can't be virtual,
just like constructors?

Thanks!
Jess

Jun 19 '07 #1
17 3539
Jess wrote:
If I have a class that has virtual but non-pure declarations, like

class A{
virtual void f();
};

Then is A still an abstract class?
No, it's not. Only classes with at least one virtual function that is
declared pure (whether its own or inherited) are abstract.
Do I have to have "virtual void
f() = 0;" instead? I think declaring a function as "=0" is the same
as not giving its definition, is this right?
No, it's not right. A pure function does not have to have a definition,
but it may. A non-pure virtual function _must_ be defined.
In addition, if I have a virtual destructor for an abstract class A,
then why do I still have to define it?
Because the language Standard requires you to.
For example, if I have

class B{
virtual ~B();
virtual void f() = 0;
};

Then my compiler still asks me to define ~B(). However, I will never
create an object of type B!
You will never create it _stand-alone_. You still can create it as
a subobject of a derived class.
Additionally, I don't think I can declare virtual constructor, but it
seems I can't make a pure constructor like

class C{
C() = 0;
virtual void f()=0;
};
The pure specifiers only apply to virtual functions.
Again, if I never make an object of type C, why am I not allowed to
declare the constructor pure?
Becuase only a virtual function can be declared pure.
Moreover, is there any function or operator that can't be virtual,
just like constructors?
Static member functions cannot be virtual. Since 'operator new'
and 'operator delete' are implicitly static, they cannot be virtual.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 19 '07 #2
Thanks a lot!

On Jun 19, 11:02 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
Jess wrote:
If I have a class that has virtual but non-pure declarations, like
class A{
virtual void f();
};
Then is A still an abstract class?

No, it's not. Only classes with at least one virtual function that is
declared pure (whether its own or inherited) are abstract.
Can a pure-function be non-virtual? I tried an example and my compiler
says no.
Do I have to have "virtual void
f() = 0;" instead? I think declaring a function as "=0" is the same
as not giving its definition, is this right?

No, it's not right. A pure function does not have to have a definition,
but it may. A non-pure virtual function _must_ be defined.
I see, so I can declare a pure virtual function in a class and define
it later as in

class A{
virtual void f() = 0;
};

void A::f(){...}
In addition, if I have a virtual destructor for an abstract class A,
then why do I still have to define it?

Because the language Standard requires you to.
For example, if I have
class B{
virtual ~B();
virtual void f() = 0;
};
Then my compiler still asks me to define ~B(). However, I will never
create an object of type B!

You will never create it _stand-alone_. You still can create it as
a subobject of a derived class.
Additionally, I don't think I can declare virtual constructor, but it
seems I can't make a pure constructor like
class C{
C() = 0;
virtual void f()=0;
};

The pure specifiers only apply to virtual functions.
Again, if I never make an object of type C, why am I not allowed to
declare the constructor pure?

Becuase only a virtual function can be declared pure.
Moreover, is there any function or operator that can't be virtual,
just like constructors?

Static member functions cannot be virtual. Since 'operator new'
and 'operator delete' are implicitly static, they cannot be virtual.
In that case, if I'd like a static member function to have polymorphic
behaviour, I think I need the static function to take an argument that
is a pointer to the base class object. Since this would allow the
static function to invoke an appropriate virtual function through the
pointer. Is this a correct approach?

Thanks,
Jess

Jun 19 '07 #3
On 2007-06-19 14:32, Jess wrote:
Hello,

If I have a class that has virtual but non-pure declarations, like

class A{
virtual void f();
};

Then is A still an abstract class? Do I have to have "virtual void
f() = 0;" instead? I think declaring a function as "=0" is the same
as not giving its definition, is this right?
A class is abstract if you can not create an instance of it (which
happens when at least one of it's members are pure virtual). Consider
these the classes:

class NotAbstract {
virtual void foo() { /* ... */ }
virtual void bar() { /* ... */ }
};

class Abstract {
virtual void foo() = 0;
virtual void bar() { /* ... */ }
};

class PureAbstract {
virtual void foo() = 0;
virtual void bar() = 0;
};
In addition, if I have a virtual destructor for an abstract class A,
then why do I still have to define it? For example, if I have

class B{
virtual ~B();
virtual void f() = 0;
};

Then my compiler still asks me to define ~B(). However, I will never
create an object of type B!
Because by not adding =0 you tell the compiler that you will supply a
definition of the destructor.
Additionally, I don't think I can declare virtual constructor, but it
seems I can't make a pure constructor like

class C{
C() = 0;
virtual void f()=0;
};

Again, if I never make an object of type C, why am I not allowed to
declare the constructor pure?

Moreover, is there any function or operator that can't be virtual,
just like constructors?
If you'll never going to create an object of type B, what would you need
a constructor for?

If you are trying to create a pure abstract class then they generally
look like this:

class Abstract {
virtual void foo() = 0;
virtual int bar(float) = 0;
// ..
virtual ~Abstract() = 0;
}

--
Erik Wikström
Jun 19 '07 #4
Jess wrote:
Thanks a lot!
You're welcome.
On Jun 19, 11:02 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
>Jess wrote:
>>If I have a class that has virtual but non-pure declarations, like
>>class A{
virtual void f();
};
>>Then is A still an abstract class?

No, it's not. Only classes with at least one virtual function that
is declared pure (whether its own or inherited) are abstract.

Can a pure-function be non-virtual? I tried an example and my compiler
says no.
Right. Trust your compiler on this.
>> Do I have to have "virtual void
f() = 0;" instead? I think declaring a function as "=0" is the same
as not giving its definition, is this right?

No, it's not right. A pure function does not have to have a
definition, but it may. A non-pure virtual function _must_ be
defined.

I see, so I can declare a pure virtual function in a class and define
it later as in

class A{
virtual void f() = 0;
};

void A::f(){...}
Yes, you may.
>[..static member functions cannot be virtual..]

In that case, if I'd like a static member function to have polymorphic
behaviour, I think I need the static function to take an argument that
is a pointer to the base class object. Since this would allow the
static function to invoke an appropriate virtual function through the
pointer. Is this a correct approach?

Uh... Well, yes, but that's not really "polymorphi c behaviour" of the
static function. The static function will invoke polymorphic behaviour
of the object. If you need a member function to have polymorphic
behaviour, it has to be non-static and then the object parameter is
implicit. It's just the terminology we use.

If you're curious, you should look for "static virtual" discussions in
the news archives. There is a valid case where a static virtual could
have its place. But let's not start this discussion again, shall we?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 19 '07 #5
On Jun 19, 11:42 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
Jess wrote:
Thanks a lot!

You're welcome.
On Jun 19, 11:02 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
Jess wrote:
If I have a class that has virtual but non-pure declarations, like
>class A{
virtual void f();
};
>Then is A still an abstract class?
No, it's not. Only classes with at least one virtual function that
is declared pure (whether its own or inherited) are abstract.
Can a pure-function be non-virtual? I tried an example and my compiler
says no.

Right. Trust your compiler on this.
> Do I have to have "virtual void
f() = 0;" instead? I think declaring a function as "=0" is the same
as not giving its definition, is this right?
No, it's not right. A pure function does not have to have a
definition, but it may. A non-pure virtual function _must_ be
defined.
I see, so I can declare a pure virtual function in a class and define
it later as in
class A{
virtual void f() = 0;
};
void A::f(){...}

Yes, you may.
[..static member functions cannot be virtual..]
In that case, if I'd like a static member function to have polymorphic
behaviour, I think I need the static function to take an argument that
is a pointer to the base class object. Since this would allow the
static function to invoke an appropriate virtual function through the
pointer. Is this a correct approach?

Uh... Well, yes, but that's not really "polymorphi c behaviour" of the
static function. The static function will invoke polymorphic behaviour
of the object. If you need a member function to have polymorphic
behaviour, it has to be non-static and then the object parameter is
implicit. It's just the terminology we use.

If you're curious, you should look for "static virtual" discussions in
the news archives. There is a valid case where a static virtual could
have its place. But let's not start this discussion again, shall we?
Certainly! Thanks. :)
Jess
Jun 19 '07 #6
On Jun 19, 11:20 pm, Erik Wikström <Erik-wikst...@telia. comwrote:
On 2007-06-19 14:32, Jess wrote:
Hello,
If I have a class that has virtual but non-pure declarations, like
class A{
virtual void f();
};
Then is A still an abstract class? Do I have to have "virtual void
f() = 0;" instead? I think declaring a function as "=0" is the same
as not giving its definition, is this right?

A class is abstract if you can not create an instance of it (which
happens when at least one of it's members are pure virtual). Consider
these the classes:

class NotAbstract {
virtual void foo() { /* ... */ }
virtual void bar() { /* ... */ }

};

class Abstract {
virtual void foo() = 0;
virtual void bar() { /* ... */ }

};

class PureAbstract {
virtual void foo() = 0;
virtual void bar() = 0;

};
Thanks! I'm just a bit curious: is there any particular situation
when I should prefer classes like PureAbstract over Abstract (or the
other way round)?
Jess

Jun 19 '07 #7
Jess wrote:
On Jun 19, 11:20 pm, Erik Wikström <Erik-wikst...@telia. comwrote:
>On 2007-06-19 14:32, Jess wrote:
>>Hello,
>>If I have a class that has virtual but non-pure declarations, like
>>class A{
virtual void f();
};
>>Then is A still an abstract class? Do I have to have "virtual void
f() = 0;" instead? I think declaring a function as "=0" is the same
as not giving its definition, is this right?

A class is abstract if you can not create an instance of it (which
happens when at least one of it's members are pure virtual). Consider
these the classes:

class NotAbstract {
virtual void foo() { /* ... */ }
virtual void bar() { /* ... */ }

};

class Abstract {
virtual void foo() = 0;
virtual void bar() { /* ... */ }

};

class PureAbstract {
virtual void foo() = 0;
virtual void bar() = 0;

};

Thanks! I'm just a bit curious: is there any particular situation
when I should prefer classes like PureAbstract over Abstract (or the
other way round)?
Purists (pun intended) would insist on defining all your base classes
like 'PureAbstract' in your example. Generally speaking, if there can
be a "default" behaviour for a virtual function, you should put it in
the base class, IMO, so that function is non-pure.

There are several idioms related to all this. For example, to make
a class abstract, yet fully defined, you only need to make its d-tor
pure (you still need to define it). That would prevent such class
from being instatiated, but you won't have to redefine any of its
behaviour if you don't want to.

The rule I try to follow is, "only make those functions pure that you
don't have a defined behaviour for". So, it's different for every
case.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 19 '07 #8
On Jun 19, 2:32 pm, Jess <w...@hotmail.c omwrote:
If I have a class that has virtual but non-pure declarations, like
class A{
virtual void f();
};
Then is A still an abstract class?
No.
Do I have to have "virtual void
f() = 0;" instead?
If you want the class to be abstract. Doing so has other
repercusions, however.

In practice, "abstract" represents a restriction on what can be
done with the class. It's never something you absolutely need
from a programming point of view; the fact that a class is
abstract is rather a consequence of the fact that you need pure
virtual functions.
I think declaring a function as "=0" is the same
as not giving its definition, is this right?
Not at all. The rules are far more subtle. Declaring a
function pure virtual (i.e. appending "= 0" to its declaration)
has several effects:

1. it makes the class abstract,

2. it means that anytime dynamic lookup of the function
resolves to the function in this class, you have undefined
behavior, and

3. it means that you are not required to provide a definition
of the function unless it is explicitly called.

Concerning these points;

1. You cannot create an instance of an abstract class.
Attention, however. This does not mean that there are never
objects which have the dynamic type of the class. During
construction and destruction, the dynamic type evolves to
alway be that of the constructor or destructor. So if you
call a pure virtual function (directly or indirectly) while
executing the constructor or the destructor, the dynamic
resolution will result in the pure virtual function. Which
leads to point 2:

2. It's undefined behavior. From a quality of implementation
point of view, I would expect the program to abort, with an
error message, and this is, in fact, what most compilers do.
But it's not guaranteed, and you cannot count on it.
Literally anything can happen, and you must absolutely avoid
the case.

3. Normally, if a function is virtual, it is considered to be
used, regardless of whether you ever actually call it or
not. And if a function is used, it must defined, somewhere.
If a function is pure virtual, however, it is not
automatically considered used, and so a definition is only
required if you actually do use it; since it cannot be found
by dynamic lookup (point 2), the only way to use it is to
call it explicitly, i.e. Base::f(). Note that the compiler
will generate such calls to the same function in the base
class implicitly in constructors, the destructor, and in a
compiler generated assignment operator. The constructors
are irrelevant here, since you cannot have a pure virtual
constructor, but if you have a pure virtual destructor, you
will have to provide a definition, and if you have a pure
virtual assignment operator (which I definitly don't
recommend), you will have to provide a definition if any of
the derived classes wants to use the default assignment
operator.
In addition, if I have a virtual destructor for an abstract class A,
then why do I still have to define it?
Because the compiler will generate a call to it in the
destructor of derived class, see point 3 above.
For example, if I have
class B{
virtual ~B();
virtual void f() = 0;
};
Then my compiler still asks me to define ~B(). However, I
will never create an object of type B!
No, but the compiler generates calls to the destructor in the
destructors of the derived classes. If you never derive from B,
you don't have to provide a definition of ~B(), but if you can't
instantiate the class, and you can't derive from it, what can
you do with it.
Additionally, I don't think I can declare virtual constructor,
but it seems I can't make a pure constructor like
class C{
C() = 0;
virtual void f()=0;
};
You can only make a virtual function pure. Since constructors
can't be virtual, they can't be pure.
Again, if I never make an object of type C, why am I not allowed to
declare the constructor pure?
Because constructors aren't virtual.
Moreover, is there any function or operator that can't be virtual,
just like constructors?
Static functions, including member operator new() and member
operator delete().

The above is rather abstract. Perhaps a quick explination of
the motivation behind it, or rather, how a compiler typically
implements it, would help:

The usual implementation of virtual functions (forgetting
multiple inheritance, etc., for the moment) is to define a table
of "function addresses" (in quotes, because we're at the
assembler level here, and this has nothing to do with any C++
type) for each class with at least one virtual function, and to
add a hidden pointer to this table in each class. (The table is
traditionally refered to as a vtbl, and the pointer as vptr,
from their names in the CFront generated C code.) A virtual
function is always considered "used" because the compiler must
take its address (which requires a definition) in order to
generate the vtbl. The point of declaring a function pure
virtual is to tell the compiler that it will not be called for
an object of this type, so the compiler does not need to take
its address and put it in the vtbl. (One early compiler I used
put a null pointer in its place, so the program silently died.
Most modern compilers put the address of a special function,
which outputs an error message and aborts, so you know why the
program died. And optimization may cause other effects.)
Because the compiler doesn't need the address for the vtbl, you
don't have to provide a definition.
>From the compiler point of view, there would be no problem
allowing the instantiation of a class with a pure virtual
function. But a virtual function which you cannot call
virtually is almost certainly an error, so the language declares
the class abstract, and forbids its instantiation.

--
James Kanze (GABI Software, from CAI) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 20 '07 #9
On Jun 19, 4:13 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
Jess wrote:
On Jun 19, 11:20 pm, Erik Wikström <Erik-wikst...@telia. comwrote:
[...]
class NotAbstract {
virtual void foo() { /* ... */ }
virtual void bar() { /* ... */ }
};
class Abstract {
virtual void foo() = 0;
virtual void bar() { /* ... */ }
};
class PureAbstract {
virtual void foo() = 0;
virtual void bar() = 0;
};
Thanks! I'm just a bit curious: is there any particular situation
when I should prefer classes like PureAbstract over Abstract (or the
other way round)?
Purists (pun intended) would insist on defining all your base classes
like 'PureAbstract' in your example.
Then they reject the template method pattern, and most of what
was done in Smalltalk. (But I fear you're right, and that there
are people who insist on such things.)

In general, I've not heard the name pure abstract class, but
rather interface, for such classes. Probably an influence from
Java, which has a special keyword for such classes, and allows
multiple inheritance from them (but not from other classes). In
practice, of course, most real interfaces will want to define a
contract, which means that the public functions will be
non-virtual, forwarding to private (or protected) pure virtual
functions.
Generally speaking, if there can
be a "default" behaviour for a virtual function, you should put it in
the base class, IMO, so that function is non-pure.
Not necessarily. There are three possibilities:

-- The base class offers no default behavior. Classical pure
virtual, without an implementation.

-- The base class offers a default behavior, but requires that
the derived class use it explicitly. Pure virtual function
with an implementation; if the derived class wants the
default, it implements the function to simply call the base
class function.

-- The base class offers a default behavior which will be used
automatically if the derived class does nothing. Just a
normal virtual function.

(I'm not saying that the second possibility is really that
useful; I've never used it. But it does exist.)

--
James Kanze (GABI Software, from CAI) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 20 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
5025
by: richard.forrest1 | last post by:
I have a problem with an abstract interface class whose implementation classes need to return different iterator types (but with the same value_types etc). Classes A and B both conform to the same abstract Interface class. Interface has a pair of virtual functions begin() and end() that generate a typical STL style range. Classes A and B provide different implementations, maybe using different types of container. The problem is that, to...
62
3377
by: christopher diggins | last post by:
Since nobody responded to my earlier post , I thought I would try to explain what I am doing a bit differently. When multiply inheriting pure virtual (abstract) base classes, a class obviously bloats quickly for each new vtable needed. Execution slows down considerably as well. You can work around this by using interfaces referemnces which have a pointer to the object and a pointer to an external function lookup table. This technique...
10
1564
by: Britney | last post by:
1. what are virutal functions and how are they differenet from overloaded function? 2. what are interfaces and how are they different from abstract classes?
6
3134
by: Alden Pierre | last post by:
Hello, http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.7 As per the link above it's wise to have a virtual deconstructor when creating an abstract class. Here is when I'm little confused. Am I deleting the right object when I call the virtual deconstructor? I was under impression when creating a class if I'm not specifically allocating memory, do not implement deconstructor and let the default take care of it...
7
3087
by: eric | last post by:
hello i'm confused by an example in the book "Effective C++ Third Edition" and would be grateful for some help. here's the code: class Person { public: Person(); virtual ~Person(); // see item 7 for why this is virtual ...
14
4209
by: v4vijayakumar | last post by:
Why we need "virtual private member functions"? Why it is not an (compile time) error?
0
9367
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9131
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9064
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8007
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6669
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4484
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4753
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2576
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2130
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.