slicing copy, what's wrong with abstract class?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • baibaichen

    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

  • Earl Purple

    #2
    Re: slicing copy, what's wrong with abstract class?


    baibaichen wrote:[color=blue]
    > 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[/color]


    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.
    [color=blue]
    > what's something with me or the book?
    >
    > thanks[/color]

    Comment

    • Axter

      #3
      Re: slicing copy, what's wrong with abstract class?

      baibaichen wrote:[color=blue]
      > 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?
      >[/color]

      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.

      Comment

      • Earl Purple

        #4
        Re: slicing copy, what's wrong with abstract class?


        Axter wrote:[color=blue]
        > To my knowledge, there is no way to avoid slicing with abstract logic.[/color]

        Didn't you read my above post? I just showed how it can be done.
        [color=blue]
        > 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.[/color]

        No but you can make copying and copy-construction protected. That
        prevents slicing whilst allowing the derived classes to have copy and
        assignment semantics.
        [color=blue]
        > 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.[/color]

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

        Comment

        • Axter

          #5
          Re: slicing copy, what's wrong with abstract class?


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

          That can only prevent slicing using value semantics. It can not
          prevent slicing using pointer semantics.
          [color=blue]
          >[color=green]
          > > 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.[/color]
          >
          > No but you can make copying and copy-construction protected. That
          > prevents slicing whilst allowing the derived classes to have copy and
          > assignment semantics.[/color]

          Again, that does not prevent slicing in pointer semantics. Only for
          value semantics.
          [color=blue][color=green]
          > > 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.[/color]
          >
          > No doubt yet another case for the Axter clone-pointer.[/color]

          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.

          Comment

          • Stephan Brönnimann

            #6
            Re: slicing copy, what's wrong with abstract class?

            Axter wrote:
            [snip][color=blue]
            > I have not found any method that can stop slicing for abstract types at
            > compile time.[/color]

            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

            Comment

            • Axter

              #7
              Re: slicing copy, what's wrong with abstract class?


              Stephan Brönnimann wrote:[color=blue]
              > Axter wrote:
              > [snip][color=green]
              > > I have not found any method that can stop slicing for abstract types at
              > > compile time.[/color]
              >
              > 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_;
              > };
              >[/color]
              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:


              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.

              Comment

              • Earl Purple

                #8
                Re: slicing copy, what's wrong with abstract class?


                Axter wrote:[color=blue]
                > Stephan Brönnimann wrote:[color=green]
                > >
                > > 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_;
                > > };
                > >[/color]
                > FYI: Your example ahs the private and protected in reverse location.[/color]

                No it doesn't.
                [color=blue]
                > 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";}
                > };[/color]

                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.

                Comment

                • Axter

                  #9
                  Re: slicing copy, what's wrong with abstract class?


                  Earl Purple wrote:[color=blue]
                  > Axter wrote:[color=green]
                  > > Stephan Brönnimann wrote:[color=darkred]
                  > > >
                  > > > 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_;
                  > > > };
                  > > >[/color]
                  > > FYI: Your example ahs the private and protected in reverse location.[/color]
                  >
                  > No it doesn't.
                  >[color=green]
                  > > 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";}
                  > > };[/color]
                  >
                  > 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.[/color]

                  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.

                  Comment

                  • Axter

                    #10
                    Re: slicing copy, what's wrong with abstract class?


                    Earl Purple wrote:[color=blue]
                    > Axter wrote:[color=green]
                    > > Stephan Brönnimann wrote:[color=darkred]
                    > > >
                    > > > 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_;
                    > > > };
                    > > >[/color]
                    > > FYI: Your example ahs the private and protected in reverse location.[/color]
                    >
                    > No it doesn't.
                    >[color=green]
                    > > 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";}
                    > > };[/color]
                    >
                    > 1. DerivedS1 is not abstract. The problem was to prevent an ABSTRACT
                    > base-class from being sliced,[/color]

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

                    Comment

                    • Stephan Brönnimann

                      #11
                      Re: slicing copy, what's wrong with abstract class?

                      Axter wrote:[color=blue]
                      > Stephan Brönnimann wrote:[color=green]
                      > > Axter wrote:
                      > > [snip][color=darkred]
                      > > > I have not found any method that can stop slicing for abstract types at
                      > > > compile time.[/color]
                      > >
                      > > 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_;
                      > > };
                      > >[/color]
                      > 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.[/color]

                      Your statement was: "I have not found any method that can stop slicing
                      for abstract types at compile time."
                      Your example that slicing can be possible does not prove your original
                      statement.
                      Your code violates Scott Meyer MEC++ "Item 33: Make non-leaf classes
                      abstract." Add
                      class DerivedS1 : public BasesS1 {
                      public:
                      ~DerivedS1() = 0;
                      };
                      and see what the compiler tells you in
                      BasesS1* DerivedS1::do_c lone() const;

                      BTW: I think the semantics of clone(), do_clone() usually is to return
                      a copy
                      and not a default constructed instance of the class.

                      Regards, Stephan

                      Comment

                      • Earl Purple

                        #12
                        Re: slicing copy, what's wrong with abstract class?


                        Axter wrote:[color=blue]
                        > Base class don't get slice. It's derive classes that get slice. The
                        > example shows a derived class getting slice.[/color]

                        But you didn't slice using the original base class, you derived a class
                        from it, then derived another class from that and sliced the second
                        derivation using the first one.

                        Now given these classes:

                        class Base
                        {
                        float itsFloat;
                        public:
                        explicit Base( float f=0 ) : itsFloat( f )
                        {
                        }

                        protected:
                        Base( const Base & b ) : itsFloat( b.itsFloat )
                        {
                        }

                        Base& operator=( const Base& b )
                        {
                        itsFloat = b.itsFloat;
                        return *this;
                        }

                        virtual std::ostream & output( std::ostream & os ) const
                        {
                        return os << itsFloat;
                        }
                        };

                        class Derived : public Base
                        {
                        double itsDouble;
                        public:
                        explicit Derived( double d=0.0 ) : Base( static_cast<flo at>(d*d) ),
                        itsDouble( d )
                        {
                        }

                        virtual std::ostream & output( std::ostream & os ) const
                        {
                        Base::output( os );
                        return os << ' ' << itsDouble;
                        }
                        };

                        std::ostream & operator<<( std::ostream & os, const Base & b )
                        {
                        return b.output( os );
                        }

                        Now show me how you can slice Derived. You must have a Derived, then
                        copy it or assign it to another derived but only the float part should
                        be transferred. So the float must not be the square of the double (or
                        overflow if appropriate).

                        Comment

                        • Stephan Brönnimann

                          #13
                          Re: slicing copy, what's wrong with abstract class?

                          Actually my original posted code was bogous (MEC++, item 33!) because
                          Base is not an abstract base class. We should make its destructor pure
                          virtual

                          class Base {
                          public:
                          virtual ~Base() = 0;
                          };

                          Base::~Base() {}

                          Regards, Stephan

                          Comment

                          • Earl Purple

                            #14
                            Re: slicing copy, what's wrong with abstract class?


                            Stephan Brönnimann wrote:[color=blue]
                            > Actually my original posted code was bogous (MEC++, item 33!) because
                            > Base is not an abstract base class. We should make its destructor pure
                            > virtual
                            >
                            > class Base {
                            > public:
                            > virtual ~Base() = 0;
                            > };
                            >
                            > Base::~Base() {}
                            >
                            > Regards, Stephan[/color]

                            Yes, in my post above I forgot to give Base a virtual destructor
                            altogether.

                            Comment

                            • Axter

                              #15
                              Re: slicing copy, what's wrong with abstract class?


                              Stephan Brönnimann wrote:[color=blue]
                              > Axter wrote:[color=green]
                              > > Stephan Brönnimann wrote:[color=darkred]
                              > > > 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_;
                              > > > };
                              > > >[/color]
                              > > 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.[/color]
                              >
                              > Your statement was: "I have not found any method that can stop slicing
                              > for abstract types at compile time."
                              > Your example that slicing can be possible does not prove your original
                              > statement.
                              > Your code violates Scott Meyer MEC++ "Item 33: Make non-leaf classes
                              > abstract." Add[/color]

                              Yes, you're right. However, code that performs slicing on a concrete
                              type is usually code that is breaking one rule or another.
                              The purpose to make it non-copyable, is to stop erroneous slicing code
                              from compiling.
                              You're absolutely right, in that the example code is breaking good
                              coding standards.
                              But the point is not whether the example code is breaking good coding
                              standards.
                              The point is whether non-copyable abstract class can prevent slicing
                              when using code that is breaking good coding standards.
                              It can not. Non-copyable method should be used for concrete types, and
                              it has little value for abstract types.

                              [color=blue]
                              >
                              > BTW: I think the semantics of clone(), do_clone() usually is to return
                              > a copy
                              > and not a default constructed instance of the class.[/color]

                              Yes, your right.
                              The problem is if you make the base copy constructor private, then you
                              have to use a different constructor, other then the copy constructor.
                              For this example, I wanted to keep it simple, so I just used the
                              default constructor.

                              Comment

                              Working...