472,802 Members | 1,357 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,802 software developers and data experts.

Get Derived (templated) from Base Pointer?

I have a templated class, CDerived:

template <typename TValue, typename TDraw, typename TEdit ...>
class CDerived : public CBase
{
TValue m_Value
public:

TValue& GetValue() const
{
return m_Value;
}

void Draw()
{
TDraw::Draw(this);
}

void Edit()
{
TEdit::Edit(this);
}
};

It is designed as a generic class that is constructed by passing in various "policy classes" as template arguments (different composite types are created using typedefs). I need to store pointers to CDerived objects in a container.

In order to accomplish this, I've created a non-templated CBase from which CDerived derives, in order to store the CBase* pointers in the container, since the container cannot store CDerived* pointers since they are not all of the same type due to the template arguments of CDerived.

I have a few pure virtual functions in CBase that are overriden in CDerived. In it's implementation, CDervied just makes calls to the policy classes static methods, passing in it's this pointer. This works fine as long as the virtual functions in CBase and CDerived have the same signatures (parameter types and return type).

My problem occurs in that one of the template members passed into CDerived is a Value that it holds. Value can be any arbitrary object, not necessarily a POD type. The only rule is that the TDraw, TEdit, etc. must be able to handle the TValue type.

I need to be able to call GetValue() in the container, but since the container only holds CBase* objects, it can't call GetValue(). GetValue() cannot be a virtual function because the return type is variable depending on the TValue template argument in CDerived. It cannot be a templated virtual function because templated virtual functions are not allowed (MSVC). It cannot be a simple template function because CBase does not know the return type and CBase cannot be templated if stored in a homogenous container.

I've experimented with many different approaches, including handle classes, visitor objects, chameleon objects, etc.; none of which work.

None of these work because in all cases you need to know the target types beforehand, and I don't know all of the target types because CDerived is templated with exponential combinations of template types.

It's interesting that sizeof() and typeid() obviously are able to figure out the type of the derived class from a base class pointer, but there appears to be no support in the language for figuring this out.

What I need to do is either:
1) Given a CBase* pointer, in a container that does not know beforehand what specific CDerived is pointed to, get a CDerived* pointer and be able to call methods on that pointer.
2) Have a way to store CDerived* objects on a container and get the properly-typed pointer out in the container and call methods on it (without the container knowing the pointer's type beforehand, just that the pointed-to object does implement the methods, such as GetValue() that will be called by the container).

I have a feeling that there must be some way to do this, though I have not seen anything that indicates it is possible.

Does anyone have any ideas?

~Mike
Dec 6 '07 #1
2 2850
weaknessforcats
9,208 Expert Mod 8TB
Not true:
It cannot be a templated virtual function because templated virtual functions are not allowed (MSVC).
I converted your snippet to templates then compiled and linked it using Visual Studioi.NET 2005:
Expand|Select|Wrap|Line Numbers
  1. template <typename TValue, typename TDraw, typename TEdit >
  2. class CBase
  3. {
  4.     public:
  5.         virtual TValue GetValue() const;
  6. };
  7.  
  8. template <typename TValue, typename TDraw, typename TEdit >
  9. class CDerived : public CBase<TValue,TDraw,TEdit>
  10. {
  11. TValue m_Value;
  12. public:
  13.  
  14. virtual TValue& GetValue() const
  15. {
  16. return m_Value;
  17. }
  18.  
  19. void Draw()
  20. {
  21. TDraw::Draw(this);
  22. }
  23.  
  24. void Edit()
  25. {
  26. TEdit::Edit(this);
  27. }
  28. };
  29. int main()
  30. {
  31.  
  32. }
  33.  
I will post again later.
Dec 7 '07 #2
weaknessforcats
9,208 Expert Mod 8TB
If your container has CBase* for the data, then all methods you can call have to be handled by the base class.

That means,

a) your virtual functions should be private so when a public base method is called, it can all the private method to don the work. The private method is overriden by the derrived class so it ti actually the derived method that is executed. The separates the interface from the implementation. Check out the design pattern called Template Method

b) all virtual methods of the derived class should be private

c) if a derived class has methods beyond the base class, then you use a visitor.

d) your CBase that this not a template won't work when GetValue() is a termplate method due to the different return types. Thhis forces CBase to be a template as well.
Dec 8 '07 #3

Sign in to post your reply or Sign up for a free account.

Similar topics

3
by: tirath | last post by:
Hi all, I have a templated class that derives from a non-templated abstract class. How do I then cast a base class pointer to a <templated> derived class pointer in a generalised fashion? ...
1
by: Art | last post by:
This is partially an academic question, but I'm trying to understand templates better. I have a base class that uses template parameters to define the behavior of its class. I want to subclass this...
1
by: FP | last post by:
I have a function that returns a base class pointer as in: baseClass<T>* FunctionA( ); As you can see the baseClass is templated. FunctionA is found in a third templated class. What I'm...
2
by: Siemel Naran | last post by:
This code fails compile std::auto_ptr<Base> f() { std::auto_ptr<Derived> out(new Derived()); return out; } There is ambiguity between a templated constructor and templated operator...
25
by: Jack | last post by:
Hi, Is there a general solution for the following problem: I have an array of instances of class B. Class B is publicly derived from class A. Then I have a class named Buffer that generally...
4
by: nozyrev | last post by:
Hi, I apologize in advance if this is a very dumb question. I've been struggling with this problem for some time: I have an abstract base class called Base and n derived classes D1, D2, ....Dn. I...
12
by: bgold | last post by:
Hey. I have a base class (SPRITE), and using this base class I have derived a large number of derived classes (PERSON, BULLET, MISSILE, etc.). Now, at a certain point in my program, I have a pair...
10
by: Dom Jackson | last post by:
I have a program which crashes when: 1 - I use static_cast to turn a base type pointer into a pointer to a derived type 2 - I use this new pointer to call a function in an object of the...
9
by: Steven Powers | last post by:
Imagine the following setup class Parent { virtual void doStuff(); } class Child : public Parent { virtual void doStuff(); }
3
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
0
by: lllomh | last post by:
How does React native implement an English player?
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.