473,748 Members | 8,367 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

slicing copy, what's wrong with abstract class?

i have written some code to verify how to disable slicing copy
according C++ Gotchas item 30

the follow is my class hierarchy, and note that B is abstract class!!

class B
{
public:
explicit B(INT32 i =0):i_(i){}
virtual ~B(){}
virtual void do_it() = 0;
virtual void pay() const = 0;
protected:
private:
INT32 i_;
};

class D: public B
{
public:
explicit D(INT32 j=0):B(),j_(j){ }
virtual void do_it()
{
j_ = 100;
}
virtual void pay() const {}
protected:
private:
INT32 j_;
};

accring to book, the following code can not be compiled, however it can
be compiled in the vc7.1

D d,d1(1);
B *const pb=&d1;
*pb = d; // B is abstract class, and this should be issued a compile
error according to the book
// however it can be compiled in the vc7.1

what's something with me or the book?

thanks

Jan 17 '06 #1
17 3573

baibaichen wrote:
i have written some code to verify how to disable slicing copy
according C++ Gotchas item 30

the follow is my class hierarchy, and note that B is abstract class!!

class B
{
public:
explicit B(INT32 i =0):i_(i){}
virtual ~B(){}
virtual void do_it() = 0;
virtual void pay() const = 0;
protected:
private:
INT32 i_;
};

class D: public B
{
public:
explicit D(INT32 j=0):B(),j_(j){ }
virtual void do_it()
{
j_ = 100;
}
virtual void pay() const {}
protected:
private:
INT32 j_;
};

accring to book, the following code can not be compiled, however it can
be compiled in the vc7.1

D d,d1(1);
B *const pb=&d1;
*pb = d; // B is abstract class, and this should be issued a compile
error according to the book
// however it can be compiled in the vc7.1

I don't have the book but are you sure that's what it says? Why
shouldn't it compile, operator= is public in B. Make it protected and
it won't compile but you'll still be able to assign D.
what's something with me or the book?

thanks


Jan 17 '06 #2
baibaichen wrote:
i have written some code to verify how to disable slicing copy
according C++ Gotchas item 30

the follow is my class hierarchy, and note that B is abstract class!!

class B
{
public:
explicit B(INT32 i =0):i_(i){}
virtual ~B(){}
virtual void do_it() = 0;
virtual void pay() const = 0;
protected:
private:
INT32 i_;
};

class D: public B
{
public:
explicit D(INT32 j=0):B(),j_(j){ }
virtual void do_it()
{
j_ = 100;
}
virtual void pay() const {}
protected:
private:
INT32 j_;
};

accring to book, the following code can not be compiled, however it can
be compiled in the vc7.1

D d,d1(1);
B *const pb=&d1;
*pb = d; // B is abstract class, and this should be issued a compile
error according to the book
// however it can be compiled in the vc7.1

what's something with me or the book?


To my knowledge, there is no way to avoid slicing with abstract logic.

With concrete types, you can avoid slicing by making your class
non-copyable.
This can be done by making the copy constructor and assignment operator
private, and with no implementation.
But this method will not work on abstract types.
Moreover, if you're passing raw pointers, you shouldn't get any
slicing.
With abstract pointers, you can get slicing when using smart pointers
that have clone logic.

Jan 17 '06 #3

Axter wrote:
To my knowledge, there is no way to avoid slicing with abstract logic.
Didn't you read my above post? I just showed how it can be done.
With concrete types, you can avoid slicing by making your class
non-copyable.
This can be done by making the copy constructor and assignment operator
private, and with no implementation.
But this method will not work on abstract types.
No but you can make copying and copy-construction protected. That
prevents slicing whilst allowing the derived classes to have copy and
assignment semantics.
Moreover, if you're passing raw pointers, you shouldn't get any
slicing.
With abstract pointers, you can get slicing when using smart pointers
that have clone logic.


No doubt yet another case for the Axter clone-pointer.

Jan 18 '06 #4

Earl Purple wrote:
Axter wrote:
To my knowledge, there is no way to avoid slicing with abstract logic.
Didn't you read my above post? I just showed how it can be done.


That can only prevent slicing using value semantics. It can not
prevent slicing using pointer semantics.
With concrete types, you can avoid slicing by making your class
non-copyable.
This can be done by making the copy constructor and assignment operator
private, and with no implementation.
But this method will not work on abstract types.


No but you can make copying and copy-construction protected. That
prevents slicing whilst allowing the derived classes to have copy and
assignment semantics.


Again, that does not prevent slicing in pointer semantics. Only for
value semantics.
Moreover, if you're passing raw pointers, you shouldn't get any
slicing.
With abstract pointers, you can get slicing when using smart pointers
that have clone logic.


No doubt yet another case for the Axter clone-pointer.


Sorry to say, but even my clone smart pointer does not prevent slicing.
Although it has assert logic for slicing, that will only catch the
slicing at runtime, and will not prevent it from compiling.

I have not found any method that can stop slicing for abstract types at
compile time.

Jan 18 '06 #5
Axter wrote:
[snip]
I have not found any method that can stop slicing for abstract types at
compile time.


For my understanding: could you please show how in the
following code Base can be sliced?
class Base {
public:
Base(int i = 0);
virtual ~Base();
protected:
Base(const Base& rhs);
Base& operator=(const Base& rhs);

private:
int i_;
};

Regards, Stephan

Jan 18 '06 #6

Stephan Brönnimann wrote:
Axter wrote:
[snip]
I have not found any method that can stop slicing for abstract types at
compile time.


For my understanding: could you please show how in the
following code Base can be sliced?
class Base {
public:
Base(int i = 0);
virtual ~Base();
protected:
Base(const Base& rhs);
Base& operator=(const Base& rhs);

private:
int i_;
};

FYI: Your example ahs the private and protected in reverse location.

In order to copy an abstract type, you have to use a clone method
similar to that used by boost pointer containers, or a clone method
similar to the one used by the following clone smart pointer:
http://code.axter.com/copy_ptr.h

Both method can get sliced even when base class has private copy
constructor and assignment operator.

The following example code is pulled from a recent thread in the boost
newsgroup.

class BasesS1
{
public:
virtual BasesS1* do_clone()const =0;
virtual string WhoAmI()const=0 ;
BasesS1(int i = 0):m_i(i){}
private:
BasesS1( const BasesS1& );
BasesS1& operator=( const BasesS1& );
protected:
int m_i;
};

class DerivedS1 : public BasesS1
{
public:
DerivedS1(int i = 0):BasesS1(i){}
BasesS1* do_clone()const {return new DerivedS1();}
string WhoAmI()const{r eturn "DerivedS1" ;}
};

class DerivedDerivedS 1 : public DerivedS1
{
public:
DerivedDerivedS 1(int i = 0):DerivedS1(i) {}
string WhoAmI()const{r eturn "DerivedDerived S1";}
};

void somefunction()
{
boost::ptr_vect or<BasesS1> vBaseS1_cpy1;
vBaseS1_cpy1.pu sh_back(new DerivedDerivedS 1(123));
boost::ptr_vect or<BasesS1> vBaseS1_cpy2(vB aseS1_cpy1.begi n(),
vBaseS1_cpy1.en d());
cout << vBaseS1_cpy2[0].WhoAmI() << endl;
}

The above code will produce slicing, even though the base class has
private copy constructor and assignment operator.

Jan 18 '06 #7

Axter wrote:
Stephan Brönnimann wrote:

For my understanding: could you please show how in the
following code Base can be sliced?
class Base {
public:
Base(int i = 0);
virtual ~Base();
protected:
Base(const Base& rhs);
Base& operator=(const Base& rhs);

private:
int i_;
};
FYI: Your example ahs the private and protected in reverse location.


No it doesn't.
The following example code is pulled from a recent thread in the boost
newsgroup.

class BasesS1
{
public:
virtual BasesS1* do_clone()const =0;
virtual string WhoAmI()const=0 ;
BasesS1(int i = 0):m_i(i){}
private:
BasesS1( const BasesS1& );
BasesS1& operator=( const BasesS1& );
protected:
int m_i;
};

class DerivedS1 : public BasesS1
{
public:
DerivedS1(int i = 0):BasesS1(i){}
BasesS1* do_clone()const {return new DerivedS1();}
string WhoAmI()const{r eturn "DerivedS1" ;}
};

class DerivedDerivedS 1 : public DerivedS1
{
public:
DerivedDerivedS 1(int i = 0):DerivedS1(i) {}
string WhoAmI()const{r eturn "DerivedDerived S1";}
};


1. DerivedS1 is not abstract. The problem was to prevent an ABSTRACT
base-class from being sliced, which can be done by giving it a
protected copy-constructor and protected assignment.

2. Your derived class is implementing the copying of the base class
because the base-class has left in a loophole, i.e. making its members
protected.

3. If you don't write the derived class properly it won't work, i.e. if
you overload the copy-constructor to not actually copy any of its
members. Why would you do that though?

4. You didn't answer the above poster's question.

Jan 18 '06 #8

Earl Purple wrote:
Axter wrote:
Stephan Brönnimann wrote:

For my understanding: could you please show how in the
following code Base can be sliced?
class Base {
public:
Base(int i = 0);
virtual ~Base();
protected:
Base(const Base& rhs);
Base& operator=(const Base& rhs);

private:
int i_;
};

FYI: Your example ahs the private and protected in reverse location.


No it doesn't.
The following example code is pulled from a recent thread in the boost
newsgroup.

class BasesS1
{
public:
virtual BasesS1* do_clone()const =0;
virtual string WhoAmI()const=0 ;
BasesS1(int i = 0):m_i(i){}
private:
BasesS1( const BasesS1& );
BasesS1& operator=( const BasesS1& );
protected:
int m_i;
};

class DerivedS1 : public BasesS1
{
public:
DerivedS1(int i = 0):BasesS1(i){}
BasesS1* do_clone()const {return new DerivedS1();}
string WhoAmI()const{r eturn "DerivedS1" ;}
};

class DerivedDerivedS 1 : public DerivedS1
{
public:
DerivedDerivedS 1(int i = 0):DerivedS1(i) {}
string WhoAmI()const{r eturn "DerivedDerived S1";}
};


1. DerivedS1 is not abstract. The problem was to prevent an ABSTRACT
base-class from being sliced, which can be done by giving it a
protected copy-constructor and protected assignment.

2. Your derived class is implementing the copying of the base class
because the base-class has left in a loophole, i.e. making its members
protected.

3. If you don't write the derived class properly it won't work, i.e. if
you overload the copy-constructor to not actually copy any of its
members. Why would you do that though?

4. You didn't answer the above poster's question.


I did answer the question. Abstract types can not be duplicated
directly, and must use an alternate interface like that used by boost
pointer containers or the copy_ptr.
Regardless of which method you use to copy an abstract type, it can get
slice, even with non-copyable base class.

In this thread, the purpose of making the base class non-copyable is to
stop slicing at compile time, and more specifically, to stop erroneous
slicing code from compiling. Making the base class non-copyable does
not stop erroneous abstract slicing from compiling.

Since this question is specifically referring to an abstract class,
this is more relevant.

Jan 18 '06 #9

Earl Purple wrote:
Axter wrote:
Stephan Brönnimann wrote:

For my understanding: could you please show how in the
following code Base can be sliced?
class Base {
public:
Base(int i = 0);
virtual ~Base();
protected:
Base(const Base& rhs);
Base& operator=(const Base& rhs);

private:
int i_;
};

FYI: Your example ahs the private and protected in reverse location.


No it doesn't.
The following example code is pulled from a recent thread in the boost
newsgroup.

class BasesS1
{
public:
virtual BasesS1* do_clone()const =0;
virtual string WhoAmI()const=0 ;
BasesS1(int i = 0):m_i(i){}
private:
BasesS1( const BasesS1& );
BasesS1& operator=( const BasesS1& );
protected:
int m_i;
};

class DerivedS1 : public BasesS1
{
public:
DerivedS1(int i = 0):BasesS1(i){}
BasesS1* do_clone()const {return new DerivedS1();}
string WhoAmI()const{r eturn "DerivedS1" ;}
};

class DerivedDerivedS 1 : public DerivedS1
{
public:
DerivedDerivedS 1(int i = 0):DerivedS1(i) {}
string WhoAmI()const{r eturn "DerivedDerived S1";}
};


1. DerivedS1 is not abstract. The problem was to prevent an ABSTRACT
base-class from being sliced,


Base class don't get slice. It's derive classes that get slice. The
example shows a derived class getting slice.

Jan 18 '06 #10

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

Similar topics

52
6435
by: Tony Marston | last post by:
Several months ago I started a thread with the title "What is/is not considered to be good OO programming" which started a long and interesting discussion. I have condensed the arguments into a single article which can be viewed at http://www.tonymarston.net/php-mysql/good-bad-oop.html I fully expect this to be the start of another flame war, so sharpen your knives and get stuck in!
137
7150
by: Philippe C. Martin | last post by:
I apologize in advance for launching this post but I might get enlightment somehow (PS: I am _very_ agnostic ;-). - 1) I do not consider my intelligence/education above average - 2) I am very pragmatic - 3) I usually move forward when I get the gut feeling I am correct - 4) Most likely because of 1), I usually do not manage to fully explain 3) when it comes true. - 5) I have developed for many years (>18) in many different environments,...
8
5051
by: Christian Stigen Larsen | last post by:
Consider the following: class parent { public: virtual void print() { printf("Parent\n"); } }; class child : public parent {
3
2059
by: Bryan Olson | last post by:
I recently wrote a module supporting value-shared slicing. I don't know if this functionality already existed somewhere, but I think it's useful enough that other Pythoners might want it, so here it is. Also, my recent notes on Python warts with respect to negative indexes were based on problems I encoutered debugging this module, so I'm posting it partially as a concrete example of what I was talking about.
17
16595
by: Jon Slaughter | last post by:
I'm having a little trouble understanding what the slicing problem is. In B.S.'s C++ PL3rdEd he says "Becayse the Employee copy functions do not know anything about Managers, only the Employee part of Manager is copied. ".... and gives the code above as .....
13
5017
by: blangela | last post by:
I have decided (see earlier post) to paste my Word doc here so that it will be simpler for people to provide feedback (by directly inserting their comments in the post). I will post it in 3 parts to make it more manageable. Below is a draft of a document that I plan to give to my introductory C++ class. Please note that I have purposely left out any mention of safety issues in the ctors which could be resolved thru some combination...
1
3474
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() { } // A virtual destructor
2
4706
by: Rahul | last post by:
Hi Everyone, I was working around object slicing (pass by value) and was wondering how it is specified in the standard, class A { }; class B: public A
1
2793
by: subramanian100in | last post by:
Consider class Base { .... }; class Derived : public Base { ...
0
8984
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8823
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9530
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9238
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8237
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6793
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6073
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4864
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2206
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.