nested classes and derivation

Discussion in 'C++' started by Christopher, Feb 8, 2008.

  1. Christopher

    Christopher Guest

    This is going to be hard to explain. But I am looking for rules on
    deriving nested classes in a scenario like the following:

    class TaskLauncher
    {
    // launches tasks which are child threads

    typedef std::vector<BaseTask *> Tasks
    Tasks m_tasks;

    // desire to be able to dynamic cast BaseTask pointer to a concrete
    task type
    // and be able to retreive its stats when stats can be differant
    types

    };


    class BaseTask
    {
    public:
    ...

    private:
    class TaskStats
    {
    public:
    virtual const std::string GetStats() const;

    ...

    private:
    m_somestat;
    }m_stats;
    };


    class Task1 : public BaseTask
    {
    public:
    ...

    private:
    class Task1Stats : public TaskStats
    {
    public:
    virtual const std::string GetStats() const;

    private:
    m_somestat;
    m_otherstat;
    }m_stats;
    };


    I don't really nest classes very often, but I figured it would be
    convienant when users of the class want a particualr kind of stats
    that they can qualify it with the task type. i.e Task1::m_stats or
    BaseTask::m_stats and get the proper type of stats.

    Do the names of member variables get overidden properly? i.e does
    Task1::m_stats contain a m_otherstats member?

    Is there a problem with Task1 being derived from BaseTask while its
    nested Task1Stats is derived from TaskStats?

    Did I get the syntax correct in my scenario example?
     
    Christopher, Feb 8, 2008
    #1
    1. Advertising

  2. Christopher wrote:
    > This is going to be hard to explain. But I am looking for rules on
    > deriving nested classes in a scenario like the following:
    >
    > class TaskLauncher
    > {
    > // launches tasks which are child threads
    >
    > typedef std::vector<BaseTask *> Tasks
    > Tasks m_tasks;
    >
    > // desire to be able to dynamic cast BaseTask pointer to a concrete
    > task type
    > // and be able to retreive its stats when stats can be differant
    > types
    >
    > };
    >
    >
    > class BaseTask
    > {
    > public:
    > ...
    >
    > private:
    > class TaskStats
    > {
    > public:
    > virtual const std::string GetStats() const;
    >
    > ...
    >
    > private:
    > m_somestat;
    > }m_stats;
    > };
    >
    >
    > class Task1 : public BaseTask
    > {
    > public:
    > ...
    >
    > private:
    > class Task1Stats : public TaskStats
    > {
    > public:
    > virtual const std::string GetStats() const;
    >
    > private:
    > m_somestat;
    > m_otherstat;
    > }m_stats;
    > };
    >
    >
    > I don't really nest classes very often, but I figured it would be
    > convienant when users of the class want a particualr kind of stats
    > that they can qualify it with the task type. i.e Task1::m_stats or
    > BaseTask::m_stats and get the proper type of stats.
    >
    > Do the names of member variables get overidden properly? i.e does
    > Task1::m_stats contain a m_otherstats member?


    Well, yes, but you do realise that an object of type 'Task1'
    will have _two_ members 'm_stats', don't you? The one stored
    in the base class subobject is going to be used when the base
    class function is called that refers to it, and the derived
    class 'm_stats' are going to be used by the derived class'
    member funciton. Confusion up to wazoo.

    > Is there a problem with Task1 being derived from BaseTask while its
    > nested Task1Stats is derived from TaskStats?
    >
    > Did I get the syntax correct in my scenario example?


    You probably did. I am not sure it's the right design, though.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Feb 8, 2008
    #2
    1. Advertising

  3. Christopher

    Grizlyk Guest

    Christopher wrote:
    >
    > This is going to be hard to explain. But I am looking for rules on
    > deriving nested classes in a scenario like the following:
    >
    > class TaskLauncher
    > {
    >    // launches tasks which are child threads
    >
    >    typedef std::vector<BaseTask *> Tasks;
    >    Tasks m_tasks;
    >
    > // desire to be able to dynamic cast BaseTask pointer
    > // to a concrete task type and be able to retreive
    > // its stats when stats can be differant types
    >
    > };
    >
    > class BaseTask
    > {
    > public:
    >    ...
    >
    > private:
    >    class TaskStats
    >    {
    >       public:
    >          virtual const std::string GetStats() const;
    >
    >          ...
    >
    >       private:
    >          m_somestat;
    >    }m_stats;
    >
    > };
    >
    > class Task1 : public BaseTask
    > {
    > public:
    >    ...
    >
    > private:
    >    class Task1Stats : public TaskStats
    >    {
    >       public:
    >          virtual const std::string GetStats() const;
    >
    >       private:
    >          m_somestat;
    >          m_otherstat;
    >    }m_stats;
    >
    > };
    >
    > I don't really nest classes very often, but I figured it would be
    > convienant when users of the class want a particualr kind of stats
    > that they can qualify it with the task type. i.e Task1::m_stats or
    > BaseTask::m_stats and get the proper type of stats.
    >
    > Do the names of member variables get overidden properly? i.e does
    > Task1::m_stats contain a m_otherstats member?


    Certainly, but not sure you have properly selected "private" access
    modifier for Task1::m_stats and BaseTask::m_stats, to inherite
    interface (access) you should use at least "protected", to use
    external access you should use "public".

    Of course, you need to declare for BaseTask at least one virtual
    method (destructor, for example) to do dinamic_cast<>

    > Is there a problem with Task1 being derived
    > from BaseTask while its nested Task1Stats
    > is derived from TaskStats?


    The problem is the fact that you are inheriting implementation. There
    is often hard to maintain, share and upgrade the kind of inheritance
    for a lot of classes.

    For Task1Stats - do you really want two copies of m_somestat for
    Task1Stats and Task1Stats with exact behaviour of TaskStats?

    For Task1 - do you really want Task1 with exact behaviour of BaseTask?

    Otherwise you can make abstract TaskStats and BaseTask classes and
    inherite from them:

    namespace Nabs{

    //
    class TaskStats
    {
    public:
    virtual
    const std::string
    GetStats() const
    =0;

    virtual ~TaskStats(){}
    };

    //
    class BaseTask
    {
    public:
    virtual ~BaseTask(){}
    };

    //namespace Nabs
    }

    //
    class BaseTask: public Nabs::BaseTask
    {
    protected:
    class Implementation {...};

    public:
    class TaskStats: public Nabs::TaskStats
    {
    public:
    const std::string
    GetStats() const;

    private:
    Implementation
    m_somestat;

    }m_stats;

    };

    //
    class Task1: public Nabs::BaseTask
    {
    protected:
    class Implementation {...};

    public:
    class TaskStats: public Nabs::TaskStats
    {
    public:
    const std::string
    GetStats() const;

    private:
    Implementation
    m_otherstat;

    }m_stats;
    };

    If dynamic_cast<> will be used only to select proper m_stats, then
    "virtual" access for m_stats is better - less expensive at runtime
    than dynamic_cast<>. In the case you can make abstract BaseTask and
    TaskStats

    //prev TaskStats
    namespace Nabs{
    class TaskStats;}

    //new BaseTask
    namespace Nabs{
    class BaseTask
    {
    public:
    virtual
    Nabs::TaskStats&
    task_stat()
    =0;

    virtual
    const Nabs::TaskStats&
    task_stat()const
    =0;

    virtual ~BaseTask(){}
    };}

    namespace Ncct
    {

    //
    template< class pImplementation >
    class AbstractTask: public Nabs::BaseTask
    {
    protected:
    class TaskStats: public Nabs::TaskStats
    {
    public:
    const std::string
    GetStats() const;

    private:
    pImplementation
    m_somestat;
    };

    public:
    //AbstractTask::TaskStats&
    TaskStats&
    task_stat()
    { return m_stats; }

    //const AbstractTask::TaskStats&
    const TaskStats&
    task_stat()const
    { return m_stats; }

    private:
    //AbstractTask::TaskStats
    TaskStats
    m_stats;
    };

    // ***
    //class BaseTask

    //declare & define
    class BaseImplementation {};

    //define
    template<>
    const std::string
    AbstractTask<BaseImplementation>::
    TaskStats::
    GetStats() const;

    //or
    //template<>class
    //AbstractTask<BaseImplementation>::
    // TaskStats;

    //declare
    typedef
    AbstractTask<BaseImplementation>
    BaseTask;


    // ***
    //class Task1

    //declare & define
    class Task1Implementation {};

    //define
    template<>
    const std::string
    AbstractTask<Task1Implementation>::
    TaskStats::
    GetStats() const;

    //or
    //template<>class
    //AbstractTask<Task1Implementation>::
    // TaskStats;

    //declare
    typedef
    AbstractTask<Task1Implementation>
    Task1;

    //namespace Ncct
    }

    Ncct::BaseTask task;
    Ncct::Task1 task1;
    Nabs::BaseTask *ar[]={&task,&task1};

    void foo()
    {
    ar[0]->task_stat().GetStats();
    ar[1]->task_stat().GetStats();
    }

    Maksim A. Polyanin
    http://grizlyk1.narod.ru/cpp_new
     
    Grizlyk, Feb 9, 2008
    #3
    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. Dietmar Gräbner
    Replies:
    1
    Views:
    388
    Priscilla Walmsley
    Jul 19, 2004
  2. Patrick J. Maloney
    Replies:
    2
    Views:
    570
    Patrick J. Maloney
    Nov 8, 2004
  3. Replies:
    1
    Views:
    454
    Stan Kitsis [MSFT]
    Dec 29, 2004
  4. Steven T. Hatton
    Replies:
    12
    Views:
    1,703
    Jonathan Turkanis
    Aug 20, 2004
  5. Replies:
    5
    Views:
    379
Loading...

Share This Page