472,378 Members | 1,229 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,378 software developers and data experts.

private pure virtual function

Example code in one of my books intrigues me:

class B {
public:
B* Clone() const {
B* p = DoClone();
assert(typeid(*p) == typeid(*this));
return p;
}

protected:
B(const B&);

private:
virtual B* DoClone() const = 0;
};

This will force all derived classes to implement DoClone, or else Clone in
the base class will fail in the assert. Could someone please explain why?

Is typeid of *this for some derived class D of type D or B? I'm sure *p is
of whatever type overrides DoClone, but i'm not sure about *this in the base
class function (even though a derived type is actually in place)... (i may
be getting confused by the whole don't use virtual functions in
constructors, and this pointer advice...)

Also another thing. pure virtual function is private??? What the hell??? Is
it really standard compliant? Can you override it in derived classes
(portably according to the standard) and still keep it private in derived
classes? Does it mean that virtuality of a function applies no matter whta
it's access qualifier is???

Thanks
Nov 1 '05 #1
10 7071
Martin Vorbrodt wrote:
Example code in one of my books intrigues me:

class B {
public:
B* Clone() const {
B* p = DoClone();
assert(typeid(*p) == typeid(*this));
return p;
}

protected:
B(const B&);

private:
virtual B* DoClone() const = 0;
};

This will force all derived classes to implement DoClone, or else Clone in
the base class will fail in the assert. Could someone please explain why?
typeid returns 'type_info' for the most derived class. If 'DoClone' does
not create an instance of the same class as 'this' points to when 'Clone'
is called, then the assertion fails.
Is typeid of *this for some derived class D of type D or B?
D&
I'm sure *p is
of whatever type overrides DoClone, but i'm not sure about *this in the base
class function (even though a derived type is actually in place)... (i may
be getting confused by the whole don't use virtual functions in
constructors, and this pointer advice...)
The assertion is that the most derived classes from both '*this' and '*p'
are the same.
Also another thing. pure virtual function is private??? What the hell??? Is
it really standard compliant?
Why not?
Can you override it in derived classes
(portably according to the standard) and still keep it private in derived
classes? Does it mean that virtuality of a function applies no matter whta
it's access qualifier is???


Virtuality and access specifiers are orthogonal.

V
Nov 1 '05 #2
"Martin Vorbrodt" <mv*******@gmail.com> wrote in message
news:HM******************@news-wrt-01.rdc-nyc.rr.com...
Example code in one of my books intrigues me:

class B {
public:
B* Clone() const {
B* p = DoClone();
assert(typeid(*p) == typeid(*this));
return p;
}

protected:
B(const B&);

private:
virtual B* DoClone() const = 0;
};

This will force all derived classes to implement DoClone, or else Clone in
the base class will fail in the assert. Could someone please explain why?
Clone is receiving a B pointer from DoClone. So DoClone is supposed to make
a clone of itself. Clone then checks to make sure that the clone created is
the same type os the instance of the class it's run on. I.E. If DoClone
simply does return new B* the assert will fail, since DoClone is only run on
derieved classes. If DoClone does return new D* the assert should not fail
(presuming D is the derived from B) since the typeid's will match.
Is typeid of *this for some derived class D of type D or B? I'm sure *p is
of whatever type overrides DoClone, but i'm not sure about *this in the
base class function (even though a derived type is actually in place)...
(i may be getting confused by the whole don't use virtual functions in
constructors, and this pointer advice...)
The this pointer will be a type of the instance of the class, whatever that
is. Since B is a pure virtual class, it would have to be some derieved.
Also another thing. pure virtual function is private??? What the hell???
Is it really standard compliant? Can you override it in derived classes
(portably according to the standard) and still keep it private in derived
classes? Does it mean that virtuality of a function applies no matter whta
it's access qualifier is???


pure virtual can be public or private (not sure about protected). Public or
private really doesn't matter as far as pure virtual is concerned I don't
believe.
Nov 1 '05 #3
Jim Langston wrote:

pure virtual can be public or private (not sure about protected). Public or
private really doesn't matter as far as pure virtual is concerned I don't
believe.


Private pure virtual functions don't make much sense, since they can't
be overridden. Protected pure virtuals do. e.g.:

class Base {
public:
void SomeFunc()
{
DoSomethingVirtually();
}
protected:
virtual void DoSomethingVirtually() = 0;
};
Nov 2 '05 #4
"red floyd" <no*****@here.dude> wrote in message
news:BD*****************@newssvr11.news.prodigy.co m...
Jim Langston wrote:

pure virtual can be public or private (not sure about protected). Public
or private really doesn't matter as far as pure virtual is concerned I
don't believe.


Private pure virtual functions don't make much sense, since they can't be
overridden. Protected pure virtuals do. e.g.:

class Base {
public:
void SomeFunc()
{
DoSomethingVirtually();
}
protected:
virtual void DoSomethingVirtually() = 0;
};


not according to Victor ;)
Nov 2 '05 #5
* red floyd:
Jim Langston wrote:

pure virtual can be public or private (not sure about protected). Public or
private really doesn't matter as far as pure virtual is concerned I don't
believe.


Private pure virtual functions don't make much sense, since they can't
be overridden.


They can be overridden.

Access is orthogonal to virtuality.

I think this is in the FAQ somewhere, check it out.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 2 '05 #6
Alf P. Steinbach wrote:
* red floyd:
Jim Langston wrote:
pure virtual can be public or private (not sure about protected). Public or
private really doesn't matter as far as pure virtual is concerned I don't
believe.


Private pure virtual functions don't make much sense, since they can't
be overridden.

They can be overridden.

Access is orthogonal to virtuality.

I think this is in the FAQ somewhere, check it out.


OK, thanks. However, I submit that it's not a good idea, because you
may get unexpected behavior.
Nov 2 '05 #7
* red floyd:
Alf P. Steinbach wrote:
* red floyd:
Jim Langston wrote:

pure virtual can be public or private (not sure about protected). Public or
private really doesn't matter as far as pure virtual is concerned I don't
believe.

Private pure virtual functions don't make much sense, since they can't
be overridden.

They can be overridden.

Access is orthogonal to virtuality.

I think this is in the FAQ somewhere, check it out.


OK, thanks. However, I submit that it's not a good idea, because you
may get unexpected behavior.


Sometimes. Generally it's opposite, because a pure virtual function in
a class T that has an implementation in class T can be confusing: there
is then the question of what that implementation is meant for, e.g., is
it required to be called by any derived class' implementation?

When a pure virtual function has no implementation in the class it's
declared in, as is the most common, then there is no implementation that
_can_ be made available to derived classes. All that a derived class
can do is to implement it or redeclare it.

Hence it's meaningless to make that pure virtual function protected
(there is nothing callable), and so it's IMO better to make it private;
at least that's not meaningless. More generally, unless a member
function's implementation is meant to be callable by derived classes, it
shouldn't be protected. It should then be private.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 2 '05 #8

Martin Vorbrodt wrote:
Example code in one of my books intrigues me:

class B {
public:
B* Clone() const {
B* p = DoClone();
assert(typeid(*p) == typeid(*this));
return p;
}

protected:
B(const B&);

private:
virtual B* DoClone() const = 0;
};

This will force all derived classes to implement DoClone, or else Clone in
the base class will fail in the assert. Could someone please explain why?
Well, suppose you have some X class you can call Clone() on an instance
of it it, and everything is cool. You get back an X object, because
there is an X::Clone(). Now you make a derived Y from X, but forget to
override Clone(). When you call Clone() on an instance of Y, you are
calling X::Clone(), which only clones the X parts! You get back an X
object that has no Y parts.

This programmer wanted to avoid that mistake. So firstly, he split the
clone function into two. A base class wrapper, and a DoClone() virtual
which cannot be called directly.
Is typeid of *this for some derived class D of type D or B? I'm sure *p is
typeid uses run-time type information; it gets the actual run-time
type.
of whatever type overrides DoClone, but i'm not sure about *this in the base
class function (even though a derived type is actually in place)... (i may
It doesn't matter. Both p and this are just pointers. The p pointer is
a pointer to the newly cloned object, and this is a pointer to the
object that was cloned. The assertion is simply that they both have the
same type. I.e. the bug of forgetting to override DoClone() has not
occured.
Also another thing. pure virtual function is private??? What the hell??? Is
That's so people could not call DoClone() directly, which would bypass
the safety check.

In a language with auxiliary methods, like Common Lisp, you would just
use an :around method. C++ doesn't have those, so if you want to wrap
additional advice methods around a method call, you split things up
into multiple functions, such as a base class wrapper that calls
virtual "helpers".

Here is how I would do exactly the same thing in that language:

(defmethod clone :around ((obj t))
(let ((new-obj (call-next-method)))
(assert (eq (class-of new-obj) (class-of obj))
new-obj))

The :around keyword specifies that this is an "around" auxiliary
method, and (obj t) means we have one argument called obj, which is of
class T. T is the superclass of all classes. I.e. this method is at the
root of the class hierarchy. Whenever the primary CLONE method is
called, this thing gets control first.

We call the primary CLONE method using (call-next-method), which is a
special function in the object system that an around method to pass
control down the chain. If we don't invoke this, the primary CLONE will
never be called, and around methods can choose to do that.

We catch the cloned object, bind it to the local variable NEW-OBJ, and
then assert that it has exactly the same class as OBJ.

We can now write a couple of primary methods to test. How about one
specialized for integers:

(defmethod clone ((obj integer))
obj)

we "clone" an integer just by returning it. Integers are immutable
objects, so we can return the same object and say we have cloned it.
This works just fine:

(clone 42) --> 42

Now let's write a broken CLONE, which takes a string:

(defmethod clone ((obj string))
(list 1 2)) ;; wrong!

It returns a list instead of cloning the string:

(clone "abc") --> *assertion!*

Boom, the assertion goes off, signaling a condition. Under CLISP the
assertion condition has this text:

"(EQ (CLASS-OF NEW-OBJ) (CLASS-OF OBJ)) must evaluate to a non-NIL
value."

There is no way for the programmer to call the primary CLONE method
directly; it's under the control of the method combination system.

That part is simulated in C++ by renaming the primary function to
DoClone, and then documenting that as being an internal interface, and
please would everyone go through Clone.

So when I saw this C++ class, I right away identified it as a clumsy
around method type of thingy. :)
it really standard compliant? Can you override it in derived classes
(portably according to the standard) and still keep it private in derived
classes? Does it mean that virtuality of a function applies no matter whta
it's access qualifier is???


Access specifiers don't control visibility, only access. You can
inherit a private virtual function, and override it with a public one.
The two are identified as the same function based on their name and
type signature.

Access specifiers only control which call sites are permitted to access
the member.

The real protection in this example comes not from the private:
specifier, but from the renaming of Clone to DoClone().

Someone can derive this class, and implement DoClone() as a public
function, allowing anyone to call it. They are then calling the
improper interface, because they should be going through Clone().

Nov 2 '05 #9

red floyd wrote:
Alf P. Steinbach wrote:
* red floyd:
Jim Langston wrote:

pure virtual can be public or private (not sure about protected). Public or
private really doesn't matter as far as pure virtual is concerned I don't
believe.

Private pure virtual functions don't make much sense, since they can't
be overridden.

They can be overridden.

Access is orthogonal to virtuality.

I think this is in the FAQ somewhere, check it out.


OK, thanks. However, I submit that it's not a good idea, because you
may get unexpected behavior.


Fiddling with access specifiers has no effect on run-time behavior.
Adding an access specifier can turn a program that requires no
diagnostics into a program that requires a diagnostic.

Nov 2 '05 #10
Martin Vorbrodt wrote:
Example code in one of my books intrigues me:

class B {
public:
B* Clone() const {
B* p = DoClone();
assert(typeid(*p) == typeid(*this));
return p;
}

protected:
B(const B&);

private:
virtual B* DoClone() const = 0;
};

This will force all derived classes to implement DoClone, or else Clone in
the base class will fail in the assert. Could someone please explain why?
Well, suppose you have some X class you can call Clone() on an instance
of it it, and everything is cool. You get back an X object, because
there is an X::Clone(). Now you make a derived Y from X, but forget to
override Clone(). When you call Clone() on an instance of Y, you are
calling X::Clone(), which only clones the X parts! You get back an X
object that has no Y parts.

This programmer wanted to avoid that mistake. So firstly, he split the
clone function into two. A base class wrapper, and a DoClone() virtual
which should not be called directly.

Is typeid of *this for some derived class D of type D or B? I'm sure *p is
typeid uses run-time type information; it gets the actual run-time
type.
of whatever type overrides DoClone, but i'm not sure about *this in the base
class function (even though a derived type is actually in place)... (i may
It doesn't matter. Both p and this are just pointers. The p pointer is
a pointer to the newly cloned object, and this is a pointer to the
object that was cloned. The assertion is simply that they both have the
same type. I.e. the bug of forgetting to override DoClone() has not
occured.
Also another thing. pure virtual function is private??? What the hell??? Is
It's private to remind people that it's an internal function which
should not be called directly. If it's invoked on the base class, the
call is forbidden by access. But it can still be overriden by public
DoClone() virtuals in derived classes. All derived class writers should
remember to mark their DoClone() override private: otherwise they
expose the function for direct calling.

In a language with auxiliary methods, like Common Lisp, you would just
use an :around method. C++ doesn't have those, so if you want to wrap
additional advice methods around a method call, you split things up
into multiple functions, such as a base class wrapper that calls
virtual "helpers".

Here is how I would do exactly the same thing in that language:

(defmethod clone :around ((obj t))
(let ((new-obj (call-next-method)))
(assert (eq (class-of new-obj) (class-of obj))
new-obj))

The :around keyword specifies that this is an "around" auxiliary
method, and (obj t) means we have one argument called obj, which is of
class T. T is the superclass of all classes. I.e. this method is at the
root of the class hierarchy. Whenever the primary CLONE method is
called, this thing gets control first.

We call the primary CLONE method using (call-next-method), which is a
special function in the object system that an around method to pass
control down the chain. If we don't invoke this, the primary CLONE will
never be called, and around methods can choose to do that.

We catch the cloned object, bind it to the local variable NEW-OBJ, and
then assert that it has exactly the same class as OBJ.

We can now write a couple of primary methods to test. How about one
specialized for integers:

(defmethod clone ((obj integer))
obj)

we "clone" an integer just by returning it. Integers are immutable
objects, so we can return the same object and say we have cloned it.
This works just fine:

(clone 42) --> 42

Now let's write a broken CLONE, which takes a string:

(defmethod clone ((obj string))
(list 1 2)) ;; wrong!

It returns a list instead of cloning the string:

(clone "abc") --> *assertion!*

Boom, the assertion goes off, signaling a condition. Under CLISP the
assertion condition has this text:

"(EQ (CLASS-OF NEW-OBJ) (CLASS-OF OBJ)) must evaluate to a non-NIL
value."

There is no way for the programmer to call the primary CLONE method
directly; it's under the control of the method combination system.

That part is simulated in C++ by renaming the primary function to
DoClone, and then documenting that as being an internal interface, and
please would everyone go through Clone.

So when I saw this C++ class, I right away identified it as a clumsy
around method type of thingy. :)
it really standard compliant? Can you override it in derived classes
(portably according to the standard) and still keep it private in derived
classes? Does it mean that virtuality of a function applies no matter whta
it's access qualifier is???


Access specifiers don't control visibility, only access. You can
inherit a private virtual function, and override it with a public one.
The two are identified as the same function based on their name and
type signature.

When you write a DoClone() in a base class, its subject to whatever
access specifier comes before it. It's just a new function that shadows
the base class DoClone(). The virtuality kicks in separately: because
the base class is virtual, and a shadowing function has the same type
signature, the shadowing one becomes an override.

Access specifiers only control which call sites are permitted to access
the member, not the semantics of inheritance and virtuals.

The real protection in this example comes not from the private:
specifier, but from the renaming of Clone to DoClone(). The derived
class writers can easily forget to make their DoClone() private, which
allows it to be called directly (but not through the base class, where
DoClone is private!)

The users of the class have to cooperate and go through Clone().

Nov 2 '05 #11

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

Similar topics

11
by: santosh | last post by:
Hello, I was going through the Marshal Cline's C++ FAQ-Lite. I have a doubt regarding section 33.10. Here he is declaring a pure virtual destructor in the base class. And again defining...
6
by: pakis | last post by:
I am having a problem of pure virtual function call in my project. Can anyone explaine me the causes of pure virtual function calls other than calling a virtual function in base class? Thanks
3
by: sudhir | last post by:
I defined a pure virtual function like virtual void sum()=0; <--- pure virtual function but If I defined a virtual function in a base class in case of multilevel inheritance for the base...
21
by: sks | last post by:
Hi , could anyone explain me why definition to a pure virtual function is allowed ?
10
by: John Goche | last post by:
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...
14
by: v4vijayakumar | last post by:
Why we need "virtual private member functions"? Why it is not an (compile time) error?
7
by: sam_cit | last post by:
Hi Everyone, I wanted to know as to what is the exact difference between a virtual function and a pure virtual function? Thanks in advance!!!
10
by: Rahul | last post by:
Hi, I tried to create a abstract class by having a non-virtual member function as pure, but i got a compilation error saying "only virtual member functions can be pure"... I'm trying to think...
14
by: Jack | last post by:
Hi, I meet a question with it , I did not get clear the different betteen them, for example: #include <iostream>
2
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and efficiency. While initially associated with cryptocurrencies...
0
by: antdb | last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine In the overall architecture, a new "hyper-convergence" concept was proposed, which integrated multiple engines and...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific technical details, Gmail likely implements measures...
0
Oralloy
by: Oralloy | last post by:
Hello Folks, I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA. My problem (spelled failure) is with the synthesis of my design into a bitstream, not the C++...
0
by: Carina712 | last post by:
Setting background colors for Excel documents can help to improve the visual appeal of the document and make it easier to read and understand. Background colors can be used to highlight important...
0
BLUEPANDA
by: BLUEPANDA | last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS starter kit that's not only easy to use but also...
0
by: Rahul1995seven | last post by:
Introduction: In the realm of programming languages, Python has emerged as a powerhouse. With its simplicity, versatility, and robustness, Python has gained popularity among beginners and experts...
1
by: Johno34 | last post by:
I have this click event on my form. It speaks to a Datasheet Subform Private Sub Command260_Click() Dim r As DAO.Recordset Set r = Form_frmABCD.Form.RecordsetClone r.MoveFirst Do If...
0
by: F22F35 | last post by:
I am a newbie to Access (most programming for that matter). I need help in creating an Access database that keeps the history of each user in a database. For example, a user might have lesson 1 sent...

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.