Handles and pointers

Discussion in 'C++' started by Simon Elliott, Sep 22, 2004.

  1. I have a data management class which uses a handle:

    typedef void* barHandle;

    class foo
    {
    private:
    class fooImpl;
    fooImpl* pimpl_;
    public:
    foo(void);
    virtual ~foo(void);
    barHandle FindBar(const std::string& key);
    std::string getvaluefrombar(barHandle handle, const std::string& key);
    };

    This would be used as follows:

    std::string my_value;
    barHandle my_handle = my_foo.Findbar("some_bar");
    if (my_handle)
    {
    my_value = my_foo.getvaluefrombar(my_handle, "some_value");
    }

    I want the implementation to be opaque to the user; it could be using
    XML, an SQL database or whatever. Currently it's using XML, and the
    implementation has code along these lines:

    barHandle foo::fooImpl::FindBar(const std::string& key)
    {
    TsomeXMLcontainer* elementBar FindBar(elementMain,key);
    return(elementBar); // casts TsomeXMLcontainer* to void*
    }

    std::string foo::fooImpl::getvaluefrombar
    (barHandle handle, const std::string& key)
    {
    TsomeXMLcontainer* elementBar =
    static_cast<TsomeXMLcontainer*>(barHandle);
    elementBar->GoAndFindValue(key);
    ...

    Fine as far as it goes, but not very type safe. Any recommendations for
    improving this by replacing the void* with something else?

    --
    Simon Elliott http://www.ctsn.co.uk
     
    Simon Elliott, Sep 22, 2004
    #1
    1. Advertising

  2. Simon Elliott

    Howard Guest

    "Simon Elliott" <Simon at ctsn.co.uk> wrote in message
    news:4151866f$0$94916$...
    > I have a data management class which uses a handle:
    >
    > typedef void* barHandle;


    This is just a pointer. I'm not sure if there's any "standard" for the term
    "handle", but in the code I work on, a handle is a pointer to a pointer.
    (This is true both in Windows and Mac, so at least it's common, if not
    "standard".)

    >
    > class foo
    > {
    > private:
    > class fooImpl;
    > fooImpl* pimpl_;
    > public:
    > foo(void);
    > virtual ~foo(void);
    > barHandle FindBar(const std::string& key);
    > std::string getvaluefrombar(barHandle handle, const std::string& key);
    > };
    >
    > This would be used as follows:
    >
    > std::string my_value;
    > barHandle my_handle = my_foo.Findbar("some_bar");
    > if (my_handle)
    > {
    > my_value = my_foo.getvaluefrombar(my_handle, "some_value");
    > }
    >
    > I want the implementation to be opaque to the user; it could be using
    > XML, an SQL database or whatever. Currently it's using XML, and the
    > implementation has code along these lines:
    >
    > barHandle foo::fooImpl::FindBar(const std::string& key)
    > {
    > TsomeXMLcontainer* elementBar FindBar(elementMain,key);
    > return(elementBar); // casts TsomeXMLcontainer* to void*
    > }
    >
    > std::string foo::fooImpl::getvaluefrombar
    > (barHandle handle, const std::string& key)
    > {
    > TsomeXMLcontainer* elementBar =
    > static_cast<TsomeXMLcontainer*>(barHandle);
    > elementBar->GoAndFindValue(key);
    > ...
    >
    > Fine as far as it goes, but not very type safe. Any recommendations for
    > improving this by replacing the void* with something else?
    >


    I don't see why you need to cast to anything. Why not just use a
    TsomeXMLcontainer* pointer wherever you need it? Casting to void* is, as
    you've said, not type safe. Hiding implementation details doesn't
    neccessarily mean hiding data types. If the name's too combersome, you can
    always use a typedef for that pointer (or even a #define, for simple
    symbolic replacement). Casting back and forth to void* is just a waste of
    time, and dangerous. Unless you have some third-party API/SDK that requires
    a void* parameter somewhere, don't bother. Just use the pointer type you
    need. (Even in the case where you *do* need a void*, it's best to cast it
    to that at the point of use, not carry around a void* that can get abused in
    other code.) Just my 2 cents worth...

    -Howard
     
    Howard, Sep 22, 2004
    #2
    1. Advertising

  3. On 22/09/2004, Howard wrote:

    >
    > I don't see why you need to cast to anything. Why not just use a
    > TsomeXMLcontainer* pointer wherever you need it? Casting to void*
    > is, as you've said, not type safe. Hiding implementation details
    > doesn't neccessarily mean hiding data types.


    In this case the data type exposes the underlying implementation too
    much. One day the users might want to replace the XML based
    implementation with something else, perhaps an SQL database. They would
    then need to change their source code, replacing every instance of
    TsomeXMLcontainer* with TsomeSQLresource*.

    --
    Simon Elliott http://www.ctsn.co.uk
     
    Simon Elliott, Sep 22, 2004
    #3
  4. Simon Elliott

    Howard Guest

    "Simon Elliott" <Simon at ctsn.co.uk> wrote in message
    news:41519b53$0$94922$...
    > On 22/09/2004, Howard wrote:
    >
    > >
    > > I don't see why you need to cast to anything. Why not just use a
    > > TsomeXMLcontainer* pointer wherever you need it? Casting to void*
    > > is, as you've said, not type safe. Hiding implementation details
    > > doesn't neccessarily mean hiding data types.

    >
    > In this case the data type exposes the underlying implementation too
    > much. One day the users might want to replace the XML based
    > implementation with something else, perhaps an SQL database. They would
    > then need to change their source code, replacing every instance of
    > TsomeXMLcontainer* with TsomeSQLresource*.
    >
    > --
    > Simon Elliott http://www.ctsn.co.uk


    That's where using a typedef or #define can help. Define a new symbol in
    the header for the class that implements those functions, and when you
    change the underlying functionality, you can change the definition to match.

    A better approach might be to use another class in between, which hides the
    passing of this pointer around entirely. If the user has no need to know
    what the actual variable type is, then they probably also don't actually
    need to *touch* that variable. (After all, you can't do anything useful
    with a variable if you don't know what it is, right? :)) Instead of
    returning a pointer from a function and then passing that pointer to another
    function, just call one (or two) functions in this new class to do the work
    for you, hiding the pointer entirely within that wrapper class. That's much
    more in the OO-style of doing things, I think.

    -Howard
     
    Howard, Sep 22, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alex
    Replies:
    3
    Views:
    1,507
    Alvin Bruney
    Dec 2, 2003
  2. sajohn

    using pointers and handles

    sajohn, Dec 11, 2006, in forum: C Programming
    Replies:
    3
    Views:
    372
    Sourcerer
    Dec 12, 2006
  3. raylopez99
    Replies:
    2
    Views:
    619
    kwikius
    Dec 18, 2006
  4. eino
    Replies:
    1
    Views:
    452
    =?ISO-8859-15?Q?=22Martin_v=2E_L=F6wis=22?=
    May 8, 2007
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    714
Loading...

Share This Page