Would a static_cast be better style here?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven T. Hatton

    Would a static_cast be better style here?

    The code shown below is an example from the Coin3D documentation. I believe
    the use of the C-style cast is safe under the circumstances, but from what
    I've been exposed to (TC++PL(SE)), I would favor using a static_cast. Is
    there any technical reason to favor the C-style over a static_cast?



    void foo(SoNode * node)
    {
    if (node->getTypeId() == SoFile::getClas sTypeId()) {
    SoFile * filenode = (SoFile *)node; // safe downward cast, knows the
    type
    }
    else if (node->getTypeId().is OfType(SoGroup: :getClassTypeId ())) {
    SoGroup * group = (SoGroup *)node; // safe downward cast, knows the
    type
    }
    }

    --
    STH
    Hatton's Law: "There is only One inviolable Law"
    KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
    Mozilla: http://www.mozilla.org
  • Ioannis Vranos

    #2
    Re: Would a static_cast be better style here?

    "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message
    news:XeCdnXVnxp MvReLdRVn-ig@speakeasy.ne t...[color=blue]
    > The code shown below is an example from the Coin3D documentation. I[/color]
    believe[color=blue]
    > the use of the C-style cast is safe under the circumstances, but from what
    > I've been exposed to (TC++PL(SE)), I would favor using a static_cast. Is
    > there any technical reason to favor the C-style over a static_cast?[/color]


    No, if you need a cast, use only the new C++ ones (static_cast,
    dynamic_cast, reinterprer_cas t). They are there for a reason, to help you
    identify potential problems. For example if your code crashes, the first
    thing you will do is check the reinterpret_cas ts at first.






    Ioannis Vranos

    Comment

    • Nils Petter Vaskinn

      #3
      Re: Would a static_cast be better style here?

      On Fri, 16 Apr 2004 16:14:17 +0300, Ioannis Vranos wrote:
      [color=blue]
      > "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message
      > news:XeCdnXVnxp MvReLdRVn-ig@speakeasy.ne t...[/color]
      [color=blue][color=green]
      >> Is there any technical reason to favor the C-style over a static_cast?[/color]
      >
      > No, if you need a cast, use only the new C++ ones (static_cast,
      > dynamic_cast, reinterprer_cas t).[/color]

      One advantage beeing that you can much more easily search for
      static_cast<som ething>(variabl e) than (something) variable.

      --
      NPV

      "the large print giveth, and the small print taketh away"
      Tom Waits - Step right up

      Comment

      • Peter Koch Larsen

        #4
        Re: Would a static_cast be better style here?


        "Steven T. Hatton" <susudata@setid ava.kushan.aa> skrev i en meddelelse
        news:XeCdnXVnxp MvReLdRVn-ig@speakeasy.ne t...[color=blue]
        > The code shown below is an example from the Coin3D documentation. I[/color]
        believe[color=blue]
        > the use of the C-style cast is safe under the circumstances, but from what
        > I've been exposed to (TC++PL(SE)), I would favor using a static_cast. Is
        > there any technical reason to favor the C-style over a static_cast?[/color]

        None whatsoever. Actually, I would advice you never ever use the C-style
        cast. The only purpose of it is to be compatible with C.

        /Peter


        Comment

        • Jerry Coffin

          #5
          Re: Would a static_cast be better style here?

          "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message news:<XeCdnXVnx pMvReLdRVn-ig@speakeasy.ne t>...[color=blue]
          > The code shown below is an example from the Coin3D documentation. I believe
          > the use of the C-style cast is safe under the circumstances, but from what
          > I've been exposed to (TC++PL(SE)), I would favor using a static_cast. Is
          > there any technical reason to favor the C-style over a static_cast?[/color]

          Given the situation, you _probably_ want to use a dynamic_cast instead
          of either one. Generally this is a type of situation you want to
          avoid though -- except in a few situations like re-creating an object
          that's been persisted to a stream of some sort, downcasting tends to
          indicate poor design.

          Downcasting gives you direct access to the functionality of a derived
          class. Generally speaking, the preferred method of doing this is to
          wrap that functionality in a virtual functio in the base class so you
          can use it without casting down to the derived type.

          Contrary to statements elsethread, a C-style cast can do one thing
          none of the new casts can. It has nothing to do with the question at
          hand, so I won't go into it, but it does exist.
          Later,
          Jerry.

          --
          The universe is a figment of its own imagination.

          Comment

          • Ioannis Vranos

            #6
            Re: Would a static_cast be better style here?

            "Jerry Coffin" <jcoffin@taeus. com> wrote in message
            news:b2e4b04.04 04161530.470ed2 98@posting.goog le.com...[color=blue]
            > "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message[/color]
            news:<XeCdnXVnx pMvReLdRVn-ig@speakeasy.ne t>...[color=blue][color=green]
            > > The code shown below is an example from the Coin3D documentation. I[/color][/color]
            believe[color=blue][color=green]
            > > the use of the C-style cast is safe under the circumstances, but from[/color][/color]
            what[color=blue][color=green]
            > > I've been exposed to (TC++PL(SE)), I would favor using a static_cast.[/color][/color]
            Is[color=blue][color=green]
            > > there any technical reason to favor the C-style over a static_cast?[/color]
            >
            > Given the situation, you _probably_ want to use a dynamic_cast instead
            > of either one. Generally this is a type of situation you want to
            > avoid though -- except in a few situations like re-creating an object
            > that's been persisted to a stream of some sort, downcasting tends to
            > indicate poor design.
            >
            > Downcasting gives you direct access to the functionality of a derived
            > class. Generally speaking, the preferred method of doing this is to
            > wrap that functionality in a virtual functio in the base class so you
            > can use it without casting down to the derived type.[/color]


            For downcasts static_cast is better to be used. dynami_cast is for upcasting
            and crosscasting.



            [color=blue]
            > Contrary to statements elsethread, a C-style cast can do one thing
            > none of the new casts can. It has nothing to do with the question at
            > hand, so I won't go into it, but it does exist.[/color]


            Don't tease our curiosity. Tell it. :-)






            Ioannis Vranos

            Comment

            • Kevin Goodsell

              #7
              Re: Would a static_cast be better style here?

              Ioannis Vranos wrote:
              [color=blue]
              >
              > For downcasts static_cast is better to be used. dynami_cast is for upcasting
              > and crosscasting.
              >[/color]

              "Upcasting" is never necessary, as far as I can tell. dynamic_cast is
              used for checked downcasting (e.g., if I cast from Shape to Triangle,
              ensures that the Shape really was a Triangle).

              -Kevin
              --
              My email address is valid, but changes periodically.
              To contact me please use the address from a recent posting.

              Comment

              • Ioannis Vranos

                #8
                Re: Would a static_cast be better style here?

                "Kevin Goodsell" <usenet2.spamfr ee.fusion@never box.com> wrote in message
                news:010gc.1350 3$A_4.10560@new sread1.news.pas .earthlink.net. ..[color=blue]
                >
                > "Upcasting" is never necessary, as far as I can tell. dynamic_cast is
                > used for checked downcasting (e.g., if I cast from Shape to Triangle,
                > ensures that the Shape really was a Triangle).[/color]


                Yes my silly mistake. Downcasting and crosscasting is dynamic_cast about.
                Upcasting needs no casting.







                Ioannis Vranos

                Comment

                • Steven T. Hatton

                  #9
                  Re: Would a static_cast be better style here?

                  Ioannis Vranos wrote:
                  [color=blue]
                  > "Kevin Goodsell" <usenet2.spamfr ee.fusion@never box.com> wrote in message
                  > news:010gc.1350 3$A_4.10560@new sread1.news.pas .earthlink.net. ..[color=green]
                  >>
                  >> "Upcasting" is never necessary, as far as I can tell. dynamic_cast is
                  >> used for checked downcasting (e.g., if I cast from Shape to Triangle,
                  >> ensures that the Shape really was a Triangle).[/color]
                  >
                  >
                  > Yes my silly mistake. Downcasting and crosscasting is dynamic_cast about.
                  > Upcasting needs no casting.[/color]

                  OK, which way is up? Actually, I didn't even think about that issue. But now
                  that I think about it. A dynamic_cast would be the thing to use. Upcasting
                  actually means to cast from a derived to a base class, and _does_, I'm
                  pretty sure, require a static_cast.

                  This is a little exercise I made up to try to get a handle on all this.
                  It's a very tricky topic.
                  /* Hava Fun */
                  #include <iostream>
                  #include <string>
                  using std::ostream;
                  using std::string;
                  using std::cout;

                  class A{
                  public:
                  A(const string& name = "A"):m_name(nam e)
                  {}
                  virtual ostream& toString (ostream& out) const;
                  friend ostream& operator<<(ostr eam& out, const A& a);
                  protected:
                  string m_name;
                  };

                  ostream& A::toString (ostream& out) const{
                  return out << this->m_name;
                  }

                  ostream& operator<<(ostr eam& out, const A& a)
                  {
                  return a.toString(out) ;
                  }


                  class B:public A
                  {
                  public:
                  B(const string& name = "B"):A(name )
                  {}
                  ostream& toString (ostream& out) const;

                  };

                  ostream& B::toString (ostream& out) const{
                  A::toString(out );
                  return out << this->m_name;
                  }

                  ostream& operator<<(ostr eam& out, const B& b)
                  {
                  return b.toString(out) ;
                  }

                  int main()
                  {

                  A a;
                  B b;
                  A* aa_ptr = &a;
                  A* ab_ptr = &b;
                  B* bb_ptr = &b;
                  cout << "A* aa_ptr = &a: " << *aa_ptr << std::endl;
                  cout << "A* ab_ptr = &b: " << *ab_ptr << std::endl;
                  cout << "B* bb_ptr = &b: " << *bb_ptr << std::endl;

                  ab_ptr = static_cast<A*> (&b);
                  cout<<"ab_ptr = static_cast<A*> (&b): " << *ab_ptr << std::endl;

                  ab_ptr = dynamic_cast<A* >(&b);

                  cout << "ab_ptr = dynamic_cast<A* >(&b): " << *ab_ptr << std::endl;

                  cout << "cout <<(A)*ab_ptr << std::endl;: " <<(A)*ab_ptr << std::endl;

                  cout << "cout << static_cast<A>( *ab_ptr) << std::endl;: ";
                  cout <<static_cast<A >(*ab_ptr) << std::endl;

                  cout << "cout << *dynamic_cast<A *>(ab_ptr) << std::endl;: ";
                  cout << *dynamic_cast<A *>(ab_ptr) << std::endl;
                  }

                  --
                  STH
                  Hatton's Law: "There is only One inviolable Law"
                  KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
                  Mozilla: http://www.mozilla.org

                  Comment

                  • Steven T. Hatton

                    #10
                    Erratum: Re: Would a static_cast be better style here?

                    Steven T. Hatton wrote:
                    [color=blue]
                    > class A{
                    > public:
                    > A(const string& name = "A"):m_name(nam e)
                    > {}
                    > virtual ostream& toString (ostream& out) const;[/color]

                    The next line is not necessary. It came from an earlier approach.
                    [color=blue]
                    > friend ostream& operator<<(ostr eam& out, const A& a);
                    > protected:
                    > string m_name;
                    > };[/color]

                    --
                    STH
                    Hatton's Law: "There is only One inviolable Law"
                    KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
                    Mozilla: http://www.mozilla.org

                    Comment

                    • Ioannis Vranos

                      #11
                      Re: Would a static_cast be better style here?

                      "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message
                      news:AJydnUo4pt IHRR3d4p2dnA@sp eakeasy.net...[color=blue]
                      >
                      > OK, which way is up? Actually, I didn't even think about that issue. But[/color]
                      now[color=blue]
                      > that I think about it. A dynamic_cast would be the thing to use.[/color]
                      Upcasting[color=blue]
                      > actually means to cast from a derived to a base class, and _does_, I'm
                      > pretty sure, require a static_cast.[/color]


                      No it doesn't, else inheritance would not work properly:


                      class base
                      {
                      // ...
                      public:
                      virtual void something() { // .. }
                      };


                      class derived1: public base
                      {
                      // ...
                      };

                      class derived2: public base
                      {
                      // ...
                      };



                      void some_func(const base *p)
                      {
                      p->something();
                      }

                      int main()
                      {
                      derived 1 d;

                      some_func(&d);
                      }


                      [color=blue]
                      > This is a little exercise I made up to try to get a handle on all this.[/color]


                      To get handle of what.

                      [color=blue]
                      > It's a very tricky topic.
                      > /* Hava Fun */
                      > #include <iostream>
                      > #include <string>
                      > using std::ostream;
                      > using std::string;
                      > using std::cout;
                      >
                      > class A{
                      > public:
                      > A(const string& name = "A"):m_name(nam e)
                      > {}
                      > virtual ostream& toString (ostream& out) const;
                      > friend ostream& operator<<(ostr eam& out, const A& a);
                      > protected:
                      > string m_name;
                      > };
                      >
                      > ostream& A::toString (ostream& out) const{
                      > return out << this->m_name;
                      > }
                      >
                      > ostream& operator<<(ostr eam& out, const A& a)
                      > {
                      > return a.toString(out) ;
                      > }
                      >
                      >
                      > class B:public A
                      > {
                      > public:
                      > B(const string& name = "B"):A(name )
                      > {}
                      > ostream& toString (ostream& out) const;
                      >
                      > };
                      >
                      > ostream& B::toString (ostream& out) const{
                      > A::toString(out );
                      > return out << this->m_name;
                      > }
                      >
                      > ostream& operator<<(ostr eam& out, const B& b)
                      > {
                      > return b.toString(out) ;
                      > }
                      >
                      > int main()
                      > {
                      >
                      > A a;
                      > B b;
                      > A* aa_ptr = &a;
                      > A* ab_ptr = &b;
                      > B* bb_ptr = &b;
                      > cout << "A* aa_ptr = &a: " << *aa_ptr << std::endl;
                      > cout << "A* ab_ptr = &b: " << *ab_ptr << std::endl;
                      > cout << "B* bb_ptr = &b: " << *bb_ptr << std::endl;
                      >
                      > ab_ptr = static_cast<A*> (&b);
                      > cout<<"ab_ptr = static_cast<A*> (&b): " << *ab_ptr << std::endl;
                      >
                      > ab_ptr = dynamic_cast<A* >(&b);
                      >
                      > cout << "ab_ptr = dynamic_cast<A* >(&b): " << *ab_ptr << std::endl;
                      >
                      > cout << "cout <<(A)*ab_ptr << std::endl;: " <<(A)*ab_ptr << std::endl;
                      >
                      > cout << "cout << static_cast<A>( *ab_ptr) << std::endl;: ";
                      > cout <<static_cast<A >(*ab_ptr) << std::endl;
                      >
                      > cout << "cout << *dynamic_cast<A *>(ab_ptr) << std::endl;: ";
                      > cout << *dynamic_cast<A *>(ab_ptr) << std::endl;
                      > }[/color]



                      I haven't drunk my coffee yet. May be later.







                      Ioannis Vranos

                      Comment

                      • Ioannis Vranos

                        #12
                        Re: Would a static_cast be better style here?

                        "Ioannis Vranos" <ivr@guesswh.at .emails.ru> wrote in message
                        news:c5q2ga$1st i$1@ulysses.noc .ntua.gr...[color=blue]
                        >
                        > Yes my silly mistake. Downcasting and crosscasting is dynamic_cast about.
                        > Upcasting needs no casting.[/color]


                        I took a look at TC++PL to refresh my memory and in summary dynamic_cast is
                        usually used for downcasts and crosscasts but the type of the object must be
                        polymorphic, that is to have virtual functions.

                        static_cast converts between related types, such as one pointer to another
                        in the same class hierarchy.

                        reinterpret_cas t handles conversions between unrelated types.

                        dynamic_cast is a form of run-time checked conversion, and is usually used
                        for downcasts and crosscasts and the type of the object must be
                        *polymorphic*, that is to have virtual functions.


                        So if in an hierarchy and you want to perform (compile-time checked)
                        related- type conversion use static_cast. If you want to check at runtime if
                        the types are related use dynamic_cast provided that the object is
                        polymorphic if you want the cast to not indicate failure although it is
                        correct.


                        Examples:

                        #include <iostream>

                        class A
                        {
                        };

                        class B: public A
                        {
                        };

                        int main()
                        {
                        B b;

                        A *p=&b;


                        B *bp=dynamic_cas t<B *>(p);

                        std::cout<<bp<< std::endl;
                        }

                        [color=blue]
                        > Executing: C:\Program Files\ConTEXT\C onExec.exe[/color]
                        "C:\MinGW\bin\g ++.exe" -std=c++98 -pedantic-errors -O3 -Wall "temp.cpp" -o
                        temp

                        temp.cpp: In function `int main()':
                        temp.cpp:18: error: cannot dynamic_cast `p' (of type `class A*') to type
                        `class
                        B*' (source type is not polymorphic)[color=blue]
                        > Execution finished.[/color]



                        #include <iostream>

                        class A
                        {
                        public:
                        virtual void something() const {}
                        };

                        class B: public A
                        {
                        };

                        int main()
                        {
                        B b;

                        A *p=&b;


                        B *bp=dynamic_cas t<B *>(p);

                        std::cout<<bp<< std::endl;
                        }


                        [color=blue]
                        > Executing: C:\Program Files\ConTEXT\C onExec.exe[/color]
                        "C:\MinGW\bin\g ++.exe" -std=c++98 -pedantic-errors -O3 -Wall "temp.cpp" -o
                        temp
                        [color=blue]
                        > Execution finished.[/color]





                        #include <iostream>

                        class A
                        {
                        };

                        class B: public A
                        {
                        };

                        int main()
                        {
                        B b;

                        A *p=&b;


                        B *bp=static_cast <B *>(p);

                        std::cout<<bp<< std::endl;
                        }


                        [color=blue]
                        > Executing: C:\Program Files\ConTEXT\C onExec.exe[/color]
                        "C:\MinGW\bin\g ++.exe" -std=c++98 -pedantic-errors -O3 -Wall "temp.cpp" -o
                        temp
                        [color=blue]
                        > Execution finished.[/color]






                        Ioannis Vranos



                        Ioannis Vranos

                        Comment

                        • Ioannis Vranos

                          #13
                          Re: Would a static_cast be better style here?

                          "Ioannis Vranos" <ivr@guesswh.at .emails.ru> wrote in message
                          news:c5rffn$1v6 h$1@ulysses.noc .ntua.gr...[color=blue]
                          >[/color]

                          The same put into shape:

                          I took a look at TC++PL to refresh my memory and in summary,


                          static_cast converts between related types, such as one pointer to another
                          in the same class hierarchy. The conversion is compile-time checked.

                          reinterpret_cas t handles conversions between unrelated types.

                          dynamic_cast is a form of run-time checked conversion, and the type of the
                          object must be *polymorphic*, that is to have virtual functions.


                          So if in an hierarchy and you want to perform (compile-time checked) related
                          type conversion use static_cast.

                          If you want to check at runtime if the types are related use dynamic_cast
                          provided that the object is polymorphic.

                          If you want to convert between oranges and potatoes use reinterpret_cas t.



                          Examples:

                          #include <iostream>

                          class A
                          {
                          };

                          class B: public A
                          {
                          };

                          int main()
                          {
                          B b;

                          A *p=&b;


                          B *bp=dynamic_cas t<B *>(p);

                          std::cout<<bp<< std::endl;
                          }

                          [color=blue]
                          > Executing: C:\Program Files\ConTEXT\C onExec.exe[/color]
                          "C:\MinGW\bin\g ++.exe" -std=c++98 -pedantic-errors -O3 -Wall "temp.cpp" -o
                          temp

                          temp.cpp: In function `int main()':
                          temp.cpp:18: error: cannot dynamic_cast `p' (of type `class A*') to type
                          `class
                          B*' (source type is not polymorphic)[color=blue]
                          > Execution finished.[/color]



                          #include <iostream>

                          class A
                          {
                          public:
                          virtual void something() const {}
                          };

                          class B: public A
                          {
                          };

                          int main()
                          {
                          B b;

                          A *p=&b;


                          B *bp=dynamic_cas t<B *>(p);

                          std::cout<<bp<< std::endl;
                          }


                          [color=blue]
                          > Executing: C:\Program Files\ConTEXT\C onExec.exe[/color]
                          "C:\MinGW\bin\g ++.exe" -std=c++98 -pedantic-errors -O3 -Wall "temp.cpp" -o
                          temp
                          [color=blue]
                          > Execution finished.[/color]





                          #include <iostream>

                          class A
                          {
                          };

                          class B: public A
                          {
                          };

                          int main()
                          {
                          B b;

                          A *p=&b;


                          B *bp=static_cast <B *>(p);

                          std::cout<<bp<< std::endl;
                          }


                          [color=blue]
                          > Executing: C:\Program Files\ConTEXT\C onExec.exe[/color]
                          "C:\MinGW\bin\g ++.exe" -std=c++98 -pedantic-errors -O3 -Wall "temp.cpp" -o
                          temp
                          [color=blue]
                          > Execution finished.[/color]






                          Ioannis Vranos

                          Comment

                          • Ioannis Vranos

                            #14
                            Re: Would a static_cast be better style here?

                            "Ioannis Vranos" <ivr@guesswh.at .emails.ru> wrote in message
                            news:c5rftd$205 r$1@ulysses.noc .ntua.gr...[color=blue]
                            >
                            > static_cast converts between related types, such as one pointer to another
                            > in the same class hierarchy. The conversion is compile-time checked.
                            >
                            > reinterpret_cas t handles conversions between unrelated types.
                            >
                            > dynamic_cast is a form of run-time checked conversion, and the type of the
                            > object must be *polymorphic*, that is to have virtual functions.
                            >
                            >
                            > So if in an hierarchy and you want to perform (compile-time checked)[/color]
                            related[color=blue]
                            > type conversion use static_cast.
                            >
                            > If you want to check at runtime if the types are related use dynamic_cast
                            > provided that the object is polymorphic.
                            >
                            > If you want to convert between oranges and potatoes use reinterpret_cas t.[/color]



                            And of course to convert from a derived pointer type to a base pointer type
                            there is no need to cast.






                            Ioannis Vranos

                            Comment

                            • Steven T. Hatton

                              #15
                              Re: Would a static_cast be better style here?

                              Ioannis Vranos wrote:
                              [color=blue]
                              > And of course to convert from a derived pointer type to a base pointer
                              > type there is no need to cast.[/color]

                              I believe it depends on what the objective is. If you want to call methods
                              on the base class instead of on the derived class, I'm pretty sure you need
                              a static cast to the *object* (not the pointer) when you invoke the
                              function. If you just want to point to a derived object with a base class
                              pointer, then you are correct, there is no need to cast.

                              I haven't tried it yet, but I believe you may also be able to used a scope
                              resolution operator to directly invoke a baseclass function.
                              --
                              STH
                              Hatton's Law: "There is only One inviolable Law"
                              KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
                              Mozilla: http://www.mozilla.org

                              Comment

                              Working...