Questions of designing a class

Discussion in 'C++' started by alexhong2001, Feb 18, 2004.

  1. alexhong2001

    alexhong2001 Guest

    When design a class, should always make it "derivable" as a base class? Is
    there really a situation that the designed class not "derivable"?

    When should make a member "protected"? Only when allowing the derived
    class(es) directly access it?

    Should destructor always be virtual?

    Thanks for your comments!
     
    alexhong2001, Feb 18, 2004
    #1
    1. Advertising

  2. "alexhong2001" <> wrote
    > When design a class, should always make it "derivable" as a base class?


    No. Derivation is something you need to plan and it has non-trivial efficiency
    costs.

    > Is there really a situation that the designed class not "derivable"?


    It's not a question of being "derivable", but rather of whether it makes sense
    to derive from it, and in many cases, it doesn't. For example, no one but a rank
    beginner would derive from std::string or std::vector. The derived class
    couldn't be used polymorphically and would almost certainly violate the Liskov
    Substitutability Principle.

    > When should make a member "protected"?


    I hate generalizations, but in this case, "rarely" is a good answer (and
    arguably, "never" might be a better one). Protected members make it difficult to
    modify a base class because the derived classes come to depend on its internals.
    If you absolutely insist on having protected members, I'd STRONGLY urge you to
    make them protected methods and not protected data members.

    > Should destructor always be virtual?


    No, for the same reasons as outlined in the first answer.

    Claudio Puviani
     
    Claudio Puviani, Feb 18, 2004
    #2
    1. Advertising

  3. alexhong2001

    Phlip Guest

    alexhong2001 wrote:

    > When design a class, should always make it "derivable" as a base class?


    You might think you can never ever change a class once written. People who
    think that tend to make too many things virtual.

    If you write lots of tests at the same time as you code, you become free to
    implement only the simplest design that passes the tests. But if you then
    add more tests requesting more features, you can then add code that passes
    the tests, and refactor that code into a new, clean design.

    Following this technique keeps you out of the debugger, and prevents you
    from over-designing classes. You will make classes that contain behavior -
    not specifically classes designed to be base classes. But when the time
    comes to merge interfaces into a base class, after the change you can test
    to ensure changing didn't add a bug.

    Read /Design Patterns/ to see popular ways to put objects together into
    object models.

    > Is
    > there really a situation that the designed class not "derivable"?


    std::string is not derivable - it has no virtual methods, so there's no
    reason to inherit it. Sometimes people inherit it to form a "convenience
    class" that changes its interface a little.

    But if we controlled the source to a class we would make it derivable when
    we find a reason to.

    > When should make a member "protected"? Only when allowing the derived
    > class(es) directly access it?


    I never saw a reason for "protected" but there might be one out there.
    Disregard it.

    > Should destructor always be virtual?


    Yes. This is a different topic - a Sane Subset. That means you don't write
    every possible combination of C++ statements, you only use specific
    combinations known to work, and you prefer them to all others. (Read
    /Effective C++/ and /Exceptional C++/ to learn what a thin line C++ can
    place between bad design and sanity!)

    Always use references without a reason to use pointers. Always use local
    storage without a reason to use heap storage, etc.

    C++ permits bugs in certain situations with non-virtual destructors because
    they also optimize certain other situations. So, treat a non-virtual
    destructor as the exceptional case, when you need speed, and use virtual
    destructors in all other situations.

    --
    Phlip
    http://www.xpsd.org/cgi-bin/wiki?TestFirstUserInterfaces
     
    Phlip, Feb 18, 2004
    #3
  4. alexhong2001

    Cy Edmunds Guest

    "alexhong2001" <> wrote in message
    news:WrQYb.46104$...
    > When design a class, should always make it "derivable" as a base class? Is
    > there really a situation that the designed class not "derivable"?
    >
    > When should make a member "protected"? Only when allowing the derived
    > class(es) directly access it?
    >
    > Should destructor always be virtual?
    >
    > Thanks for your comments!
    >
    >


    Well, your questions cover a lot of territory. I would say that many classes
    fall into two broad categories: concrete data types and abstract data types.
    (Not everybody uses these names, btw.) Concrete data types have no virtual
    methods and are not intended for use as base classes. They are tightly bound
    to their implementations. Example: std::complex.

    Not all destructors should be virtual. A concrete data type might have a
    destructor (e.g. std::vector) but if so it will not be virtual. If you want
    to reuse such a class, use encapsulation (aka composition) rather than
    inheritance:

    class Fred
    {
    private:
    std::vector<double> m_whatever; // good way to reuse std::vector
    ...
    };

    NOT

    class Fred : public std::vector<double> {...}; // bad way

    Abstract data types are used when you have a set or polymorphic classes:

    class IShape
    {
    public:
    virtual void draw() const = 0;
    virtual ~IShape() {}
    };

    The typical pattern is no data, no constructor, pure virtual methods, and a
    do-nothing virtual destructor. Obviously, such a class is intended as a base
    class:

    class Circle : public IShape {...};
    class Square : public IShape (...};

    The point is that if I have an IShape pointer I can draw the shape without
    knowing or caring what type it actually is.

    There are many other basic designs but those are two I use a lot.

    I don't use "protected" very often, but if I do it will contain a method
    (not data) which is intended for use by derived classes. Putting data in a
    protected area compromises encapsulation IMHO.

    --
    Cy
    http://home.rochester.rr.com/cyhome/
     
    Cy Edmunds, Feb 18, 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. E11
    Replies:
    1
    Views:
    4,848
    Thomas Weidenfeller
    Oct 12, 2005
  2. E G
    Replies:
    6
    Views:
    353
    Jumbo
    Jan 23, 2004
  3. Naren

    help in designing class

    Naren, May 25, 2004, in forum: C++
    Replies:
    1
    Views:
    309
    Victor Bazarov
    May 25, 2004
  4. Naren

    help in designing class

    Naren, May 26, 2004, in forum: C++
    Replies:
    1
    Views:
    325
    Victor Bazarov
    May 26, 2004
  5. James Brown
    Replies:
    12
    Views:
    483
    Greg Comeau
    Sep 24, 2004
Loading...

Share This Page