473,230 Members | 1,965 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

Virtual constructor & covariant return types

Here is a code from
http://www.parashift.com/c++-faq-lit....html#faq-20.8

--------------------------------------
class Shape {
public:
virtual ~Shape() { } // A virtual destructor
virtual void draw() = 0; // A pure virtual function
virtual void move() = 0;
...
virtual Shape* clone() const = 0; // Uses the copy constructor
virtual Shape* create() const = 0; // Uses the default constructor
};

class Circle : public Shape {
public:
Circle* clone() const; // Covariant Return Types; see below
Circle* create() const; // Covariant Return Types; see below
...
};

Circle* Circle::clone() const { return new Circle(*this); }
Circle* Circle::create() const { return new Circle(); }

void userCode(Shape& s)
{
Shape* s2 = s.clone();
Shape* s3 = s.create();
...
delete s2; // You need a virtual destructor here
delete s3;
}

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


It seems that behavior of the program will be the same one if we don't
use covariant return types, for instance

class Circle : public Shape {
public:
Shape* clone() const; // Non-Covariant Return Types
Shape* create() const; // Non-Covariant Return Types
...
};

Why do we need covariant return types in the "virtual constructor"
design pattern?

--
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn

Jul 5 '06 #1
8 2146
* Alex Vinokur:
>
Why do we need covariant return types in the "virtual constructor"
design pattern?
You don't absolutely /need/ them: they're a convenience feature to avoid
casts.

First, where might you actually use a covariant result? When you
statically know the type (or at least, a more specialized type than
Base) of the object you're cloning or using as an examplar. In that
case, you're avoiding a downcast in the client code.

That downcast in the client code can be avoided anyway, but at the cost
of a centralized downcast in the class' code, or the cost of not
supporting derived classes. The covariance feature removes that cost,
but only for built-in pointers and references. For smart-pointers you
have to cope with it and choose your poison.

--
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?
Jul 5 '06 #2

"Alf P. Steinbach" <al***@start.nowrote in message news:4h*************@individual.net...
* Alex Vinokur:

Why do we need covariant return types in the "virtual constructor"
design pattern?

You don't absolutely /need/ them: they're a convenience feature to avoid
casts.
[snip]

--- Covariant Return Types ---
class Circle : public Shape {
public:
Circle* clone() const;
Circle* create() const;
...
};

--- Non-Covariant Return Types ---
// Use of this class requires no casts.
class Circle : public Shape {
public:
Shape* clone() const;
Shape* create() const;
...
};
--
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn

Jul 5 '06 #3
Alex Vinokur wrote:
"Alf P. Steinbach" <al***@start.nowrote in message news:4h*************@individual.net...
>* Alex Vinokur:
>>Why do we need covariant return types in the "virtual constructor"
design pattern?
You don't absolutely /need/ them: they're a convenience feature to avoid
casts.
[snip]

--- Covariant Return Types ---
class Circle : public Shape {
public:
Circle* clone() const;
Circle* create() const;
...
};

--- Non-Covariant Return Types ---
// Use of this class requires no casts.
class Circle : public Shape {
public:
Shape* clone() const;
Shape* create() const;
...
};
Your second class does in fact require casts.

Circle aCircle;
Circle* badClone = aCircle.clone(); // ERROR!!!!
Circle* goodClone = static_cast<Circle*>(aCircle.clone);

Note that dynamic_cast would also be acceptable (assuming a virtual
function somewhere).

The first class requires no such casts, and since upcasts to the base
class (Shape) do not require a cast either, that method is preferable.
Jul 5 '06 #4

"red floyd" <no*****@here.dudewrote in message news:vC*********************@newssvr21.news.prodig y.com...
Alex Vinokur wrote:
"Alf P. Steinbach" <al***@start.nowrote in message news:4h*************@individual.net...
* Alex Vinokur:
Why do we need covariant return types in the "virtual constructor"
design pattern?
You don't absolutely /need/ them: they're a convenience feature to avoid
casts.
[snip]

--- Covariant Return Types ---
class Circle : public Shape {
public:
Circle* clone() const;
Circle* create() const;
...
};

--- Non-Covariant Return Types ---
// Use of this class requires no casts.
class Circle : public Shape {
public:
Shape* clone() const;
Shape* create() const;
...
};

Your second class does in fact require casts.

Circle aCircle;
Circle* badClone = aCircle.clone(); // ERROR!!!!
Circle* goodClone = static_cast<Circle*>(aCircle.clone);
[snip]

OK.
But my second class requires no casts for sample in http://www.parashift.com/c++-faq-lit....html#faq-20.8

--
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn

Jul 5 '06 #5
red floyd wrote:
Alex Vinokur wrote:
>"Alf P. Steinbach" <al***@start.nowrote in message
news:4h*************@individual.net...
>>* Alex Vinokur:
Why do we need covariant return types in the "virtual constructor"
design pattern?
You don't absolutely /need/ them: they're a convenience feature to
avoid casts.
[snip]

--- Covariant Return Types ---
class Circle : public Shape {
public:
Circle* clone() const;
Circle* create() const;
...
};

--- Non-Covariant Return Types ---
// Use of this class requires no casts.
class Circle : public Shape {
public:
Shape* clone() const;
Shape* create() const;
...
};

Your second class does in fact require casts.

Circle aCircle;
Circle* badClone = aCircle.clone(); // ERROR!!!!
Circle* goodClone = static_cast<Circle*>(aCircle.clone);
Nit pick:

Circle* goodClone = static_cast<Circle*>(aCircle.clone());

(you'd forgotten parentheses after 'clone')
Note that dynamic_cast would also be acceptable (assuming a virtual
function somewhere).
Why assuming? Why somewhere? Covariant return types _require_ the
function to be virtual, don't they?
The first class requires no such casts, and since upcasts to the base
class (Shape) do not require a cast either, that method is preferable.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 5 '06 #6
Alex Vinokur <al****@users.sourceforge.netwrote:
"red floyd" <no*****@here.dudewrote in message
news:vC*********************@newssvr21.news.prodig y.com...
>Alex Vinokur wrote:
>>"Alf P. Steinbach" <al***@start.nowrote in message
news:4h*************@individual.net...
>>>* Alex Vinokur:
>>>>Why do we need covariant return types in the "virtual constructor"
design pattern?
>>>You don't absolutely /need/ them: they're a convenience feature to
avoid casts.
>>[snip]

--- Covariant Return Types ---
class Circle : public Shape {
public:
Circle* clone() const;
Circle* create() const;
...
};

--- Non-Covariant Return Types ---
// Use of this class requires no casts.
class Circle : public Shape {
public:
Shape* clone() const;
Shape* create() const;
...
};
>Your second class does in fact require casts.

Circle aCircle;
Circle* badClone = aCircle.clone(); // ERROR!!!!
Circle* goodClone = static_cast<Circle*>(aCircle.clone);
OK.
But my second class requires no casts for sample in
http://www.parashift.com/c++-faq-lit....html#faq-20.8
The sample should have made use of the feature provided by covariant
return types. But it did not, that is why you do not need a cast. Change
the userCode function to:

void userCode(Circle& c)
{
Circle* s2 = c.clone();
Circle* s3 = c.create();
...
delete s2; // You need a virtual destructor here
delete s3;
}

And you will need a cast somewhere unless you use covariant return
types.

regards
--
jb

(reply address in rot13, unscramble first)
Jul 5 '06 #7

"Jakob Bieling" <ar****************@rot13.comwrote in message news:e8**********@f1node01.rhrz.uni-bonn.de...
Alex Vinokur <al****@users.sourceforge.netwrote:
[snip]
But my second class requires no casts for sample in
http://www.parashift.com/c++-faq-lit....html#faq-20.8

The sample should have made use of the feature provided by covariant
return types. But it did not, that is why you do not need a cast. Change
the userCode function to:

void userCode(Circle& c)
{
Circle* s2 = c.clone();
Circle* s3 = c.create();
...
delete s2; // You need a virtual destructor here
delete s3;
}
[snip]

I think, if we use userCode(Circle&) instead of userCode(Shape&) it is not a virtual constructor.

--
Alex Vinokur
email: alex DOT vinokur AT gmail DOT com
http://mathforum.org/library/view/10978.html
http://sourceforge.net/users/alexvn

Jul 6 '06 #8
Alex Vinokur <al****@users.sourceforge.netwrote:
"Jakob Bieling" <ar****************@rot13.comwrote in message
news:e8**********@f1node01.rhrz.uni-bonn.de...
>Alex Vinokur <al****@users.sourceforge.netwrote:
[snip]
>>But my second class requires no casts for sample in
http://www.parashift.com/c++-faq-lit....html#faq-20.8

The sample should have made use of the feature provided by
covariant return types. But it did not, that is why you do not need
a cast. Change the userCode function to:

void userCode(Circle& c)
{
Circle* s2 = c.clone();
Circle* s3 = c.create();
...
delete s2; // You need a virtual destructor here
delete s3;
}
[snip]

I think, if we use userCode(Circle&) instead of userCode(Shape&)
it is not a virtual constructor.
Right, but it makes use of covariant return types. Obviously, you
have to know the returned type at compile-time, so the virtual
construction mechanism is not used. You use one *or* the other. But
covariant return types make it possible to use both (in different
places) with the same code without the need for a cast.

--
jb

(reply address in rot13, unscramble first)
Jul 6 '06 #9

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

Similar topics

7
by: Alex Vinokur | last post by:
Hello, Here is some program with virtual constructors. Is there any difference between * clone1() vs. clone2() * create1() vs. create2() ? It seems that it should be.
2
by: Edward Diener | last post by:
In C++ an overridden virtual function in a derived class must have the exact same signature of the function which is overridden in the base class, except for the return type which may return a...
6
by: miked | last post by:
Why are there still no covariant return types? All searches reveal no workarounds accept for using an interface which is a real pain. I wind up missing this capability almost every time I...
3
by: kikazaru | last post by:
Is it possible to return covariant types for virtual methods inherited from a base class using virtual inheritance? I've constructed an example below, which has the following structure: Shape...
2
by: babaco | last post by:
Hi, I've come upon a situation where I don't understand what's happening. Basically, I'm implementing a kind of 'chain of responsibility' using some covariant types: #include <iostream>...
1
by: Bart Simpson | last post by:
Can anyone explain the concept of "slicing" with respect to the "virtual constructor" idiom as explain at parashift ? From parashift: class Shape { public: virtual ~Shape() { } ...
4
by: Rahul | last post by:
Hi Everyone, I understand that the constructors can't be virtual and parashift has the following example, to have an workaround for the constructors to be virtual, class Shape { public:...
6
by: kepeng | last post by:
There are 2 abstract base classes: class IB; class IA { //... public: virtual IB* GetB() = 0; }
1
by: mosfet | last post by:
Hi, I am trying to modify existing code to use smart pointers and I get some issues with virtual methods : class Folder : public Object { public: friend class PimItemCollection; friend...
0
by: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 3 Jan 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). For other local times, please check World Time Buddy In...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...

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.