private virtual functions and pure virtual functions with bodies

J

John Goche

Hello,

page 202 of Symbian OS Explained by Jo Stichbury states

"All virtual functions, public, protected or private, should be
exported"

then page 203 states

"In the rare cases where a pure virtual function body
has a function body, it must be exported."

------------------------------

I assume that if a derived class B implements a function f
declared private and virtual in a base class A then upon
invoking B::f an invocation of A::f will take place despite
the fact that f is private in A. Also, is it possible to
change the access specifier (e.g. from private to
protected or public in this case?).

Also, I have never seen a pure virtual function with a
body. What does this mean? I thought that whenever
a function is pure virtual it must end with a = 0 and
contain no implementation. (?)

Feedback appreciated,

Thanks,

JG
 
S

Salt_Peter

John said:
Hello,

page 202 of Symbian OS Explained by Jo Stichbury states

"All virtual functions, public, protected or private, should be
exported"

then page 203 states

"In the rare cases where a pure virtual function body
has a function body, it must be exported."

------------------------------

I assume that if a derived class B implements a function f
declared private and virtual in a base class A then upon
invoking B::f an invocation of A::f will take place despite
the fact that f is private in A.

No it won't, if A::f is private, it's private for all including for the
B derivative.
And even if A::f is public, calling B::f doesn't invoke A::f.
Also, is it possible to
change the access specifier (e.g. from private to
protected or public in this case?).
What?


Also, I have never seen a pure virtual function with a
body. What does this mean? I thought that whenever
a function is pure virtual it must end with a = 0 and
contain no implementation. (?)

nope. The class is abstract. That does not prevent you from
implementing the pure-virtual if you choose to. A nice feature to have.
Feedback appreciated,

Nothing prevents you from calling a pure virtual function, unlike other
languages.

#include <iostream>

class Base
{
public:
virtual ~Base() = 0;
virtual void foo() const = 0;
};

Base::~Base() { std::cout << "~Base()\n"; }
void Base::foo() const { std::cout << "Base::foo()\n"; }

class Derived : public Base
{
public:
Derived() { }
~Derived() { std::cout << "~Derived()\n"; }
void foo() const
{
std::cout << "Derived::foo()\n";
Base::foo();
}
};

int main()
{
Derived derived;
derived.foo();
}

/*
Derived::foo()
Base::foo()
~Derived()
~Base()
*/
 
E

eriwik

Hello,

page 202 of Symbian OS Explained by Jo Stichbury states

"All virtual functions, public, protected or private, should be
exported"

then page 203 states

"In the rare cases where a pure virtual function body
has a function body, it must be exported."

------------------------------

I assume that if a derived class B implements a function f
declared private and virtual in a base class A then upon
invoking B::f an invocation of A::f will take place despite
the fact that f is private in A.

No, a private function can not be accessed from the derived class.
Also, is it possible to
change the access specifier (e.g. from private to
protected or public in this case?).

Yes, you can declare a function public if it was private or protected
in the base-class.
Also, I have never seen a pure virtual function with a
body. What does this mean? I thought that whenever
a function is pure virtual it must end with a = 0 and
contain no implementation. (?)

Consider this:

class Base {
virtual int foo() = 0;
public:
virtual int bar();
}

int Base::foo() { return 1; }

int Base::bar() return foo(); }

class Derived : public Base {
virtual int foo();
public:
virtual int bar();
}

int Derived::bar() { return A::bar(); }

int Derived::foo() { return 0; }

int main() {
B b;
std::cout << b.bar(); // will print 1
}

This allows you to use a private pure function with a body, however
note that you must also provide a foo()-function in Derived, since it's
a pure virtual function in Base.

The use of private pure functions with bodies are perhaps not so great.
Public pure functions with bodies can be very useful in providing part
of the functionality wanted from the function, and still requireing any
derived classes to provide their own implementation, even if it's just
a Base::foo()-call.
 
J

John Goche

Thank you Erik and Peter for the clarifications,

The example really shows how a pure virtual function
must be implemented in a derived class and prevents
the base class from being instantiated directly but
that an implementation of the pure virtual function
in the base class may still exist and be accessed
from some other function in the same base class
or using an access specifier from a derived class
for example.

What is not clear to me though, is, if a private
function cannot be called from a derived class,
then what is the point of making such a
function virtual???

Thanks,

JG
 
C

Craig Scott

What is not clear to me though, is, if a private
function cannot be called from a derived class,
then what is the point of making such a
function virtual???

It is a common pattern for a public function in a base class to call a
private virtual function(s). The public base function defines *what*
steps to perform but the private virtual functions define *how* each
step is implemented. The base function is more or less just the shell
of the task and the subclass can override the private virtual functions
as required to customize how each step is performed. This is the
"Template Method" as explained in "Design Patterns" book by Gamma, et.
al. I highly recommended you get your hands on a copy (as do most
seasoned developers these days it seems!).
 
S

Salt_Peter

[ Please don't Top Post - rearranged ]

John said:
Thank you Erik and Peter for the clarifications,

The example really shows how a pure virtual function
must be implemented in a derived class and prevents
the base class from being instantiated directly but
that an implementation of the pure virtual function
in the base class may still exist and be accessed
from some other function in the same base class
or using an access specifier from a derived class
for example.

What is not clear to me though, is, if a private
function cannot be called from a derived class,
then what is the point of making such a
function virtual???

A creator programmer is writing a "rule" for the user of the class(es)
that states that a pure-virtual function *must* be implemented in order
to satisfy the requirements - thats the logic. Imagine a system that
handles elements having the requirement that some given method() be
available. Declaring the void method() as pure-virtual essentially
guarentees that the derivatives will have that void method()
implemented somewhere with the option of overriding it. Note: a derived
class doesn't have to override that function *if* its already
implemented lower in the inheritance hierarchy.

Personally, i think that making a pure-virtual private is a bad idea.
Also, suggesting that an abstract class should never have members is a
ludicrous requirement ( such members in fact would ultimately become
part of a derived entities anyways ). An interface in Java is not
allowed to have members, but no such restriction is imposed on C++.
And, IMHO, i don't see why such a restriction should be imposed.

If a given set of composition members is common to an inheritance
hierarchy, putting them elsewhere than in an abstract class is poor
code. Even for a pure interface. I find that imposing such a rule
outright is counter-productive. Except, of course, in the case where a
particular language requires it. In the case you put forth, that sounds
like a requirement made to satisfy an IDL compiler.
 
J

John Goche

Just as a note...
Here is an example of how a derived class can
invoke a private function in a base class when
such function is declared virtual:

#include <iostream>

class A {
private:
virtual void foo() = 0;
};

class B: public A {
public:
virtual void foo();
};

void B::foo() {
std::cout << "foo" << std::endl;
}

int main() {
B b;
b.foo();
}

output: foo
 
S

Salt_Peter

John said:
Just as a note...
Here is an example of how a derived class can
invoke a private function in a base class when
such function is declared virtual:

#include <iostream>

class A {
private:
virtual void foo() = 0;
};

class B: public A {
public:
virtual void foo();
};

void B::foo() {
std::cout << "foo" << std::endl;
}

int main() {
B b;
b.foo();
}

output: foo

I hate to have to disappoint you, but thats not correct. The output
comes from B::foo() (realize also that A::foo() is not even
implemented). By the way: B::foo() is already virtual.
Compile and run the following, read the output, then uncomment the call
to A::foo(). Read the error.
Note: base functions are *overriden* by virtual derived functions:
--- the derived foo() *hides* the base's foo() ---
so you must call it explicitly - and thats by design.

#include <iostream>
#include <ostream>

class A {
private:
virtual void foo() const = 0;
};

void A::foo() const {
std::cout << "A::foo()\n";
}

class B: public A {
public:
void foo() const;
};

void B::foo() const {
// A::foo(); // must be public in class A
std::cout << "B::foo()\n";
}

int main() {
B b;
b.foo();
}

/*
B::foo()
*/

Finally, consider what happens if you derive from class B like this:

class C : public B
{
};

int main()
{
C c;
c.foo(); // this works !!!
}

Do you understand now If you don't overide foo() what happens?
Class A does not require all/each of its derivatives to implement
foo(), as long as foo() is indeed implemented somewhere down the
hierarchy, its indeed callable.
 
M

Marcus Kwok

Salt_Peter said:
Personally, i think that making a pure-virtual private is a bad idea.

Guru Sutter disagrees with you:

"When should virtual functions be public, protected, or private?"

The short answer is: Rarely if ever, sometimes, and by default,
respectively - the same answer we've already learned for other kinds
of class members.

http://www.gotw.ca/publications/mill18.htm
 
S

Salt_Peter

Marcus said:
Guru Sutter disagrees with you:

"When should virtual functions be public, protected, or private?"

The short answer is: Rarely if ever, sometimes, and by default,
respectively - the same answer we've already learned for other kinds
of class members.

http://www.gotw.ca/publications/mill18.htm

I'm already aware of the above. And my response is that if anything
classifies a virtual function as one that should be private or
protected, that *anything* shouldn't be placed in the virtual function
at all. Place private parts in private member functions instead.
Needless to say, that can't always lead to a viable solution.
 
M

Marcus Kwok

Salt_Peter said:
I'm already aware of the above. And my response is that if anything
classifies a virtual function as one that should be private or
protected, that *anything* shouldn't be placed in the virtual function
at all. Place private parts in private member functions instead.

I'm sorry, I'm having a little trouble parsing the above...

The article is saying that by default the virtual should be private, and
should only be made public if there is a compelling reason to do so, and
have a public non-virtual call the private virtual. This way, the
interface (non-virtual function) is separated from the implementation
(virtual function). If you have a public virtual, then it is specifying
both.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top