|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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? |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
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 |
|
![]() |
| Outils de la discussion | |
|
|