473,385 Members | 1,331 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,385 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 2152
* 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: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

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.