By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,107 Members | 1,562 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,107 IT Pros & Developers. It's quick & easy.

"Virtual constructor" and slicing

P: n/a
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() { } // 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(); }

In the clone() member function, the new Circle(*this) code calls
Circle's copy constructor to copy the state of this into the newly
created Circle object. (Note: unless Circle is known to be final (AKA a
leaf), you can reduce the chance of slicing by making its copy
constructor protected.) In the create() member function, the new
Circle() code calls Circle's default constructor.

May 23 '07 #1
Share this Question
Share on Google+
1 Reply


P: n/a
* Bart Simpson:
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() { } // 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(); }

In the clone() member function, the new Circle(*this) code calls
Circle's copy constructor to copy the state of this into the newly
created Circle object. (Note: unless Circle is known to be final (AKA a
leaf), you can reduce the chance of slicing by making its copy
constructor protected.) In the create() member function, the new
Circle() code calls Circle's default constructor.
Slicing is when only the (or more precisely, a) base class part of an
object is copied.

It can happen with clone() and, interpreting the word slicing very
liberally, with create() when the functions aren't properly overridden
and reimplemented in a derived class.

Mostly that's boilerplate code that could in principle be generated
automatically, and in practice you can do that via macros (if you're not
afraid of name collisions and other issues with macros). But as far as
I know nobody's found of way of ensuring at compile time that a class
does override a concrete member function, and in turn imposes that
requirement on its derived classes. Or even without the latter feature.

However, while you can't (AFAIK) detect at compile time or run time
whether the proper clone() function is called, you can detect at run
time that it's a wrong one, e.g.

Circle* clone() const
{
if( typeid( *this ) != typeid( Circle ) ) { throw "Urgh"; }
return new Circle( *this );
}

It's better than nothing, but both the cloning business and e.g. the
visitor pattern shows that there is most likely a very basic and general
language feature missing, something that does away with manually
replicating boilerplate code in the classes.

--
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?
May 23 '07 #2

This discussion thread is closed

Replies have been disabled for this discussion.