Jump to content
  • Advertisement
Sign in to follow this  
Timkin

Calling virtual functions from nested base classes?

This topic is 5410 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to get the following to work but I cannot... the summary is that I have a base class that contains a nested class. The base class is a manager class for its nested class. I want to derive different instances of the manager class and each of these instances cause the nested base class instance to be constructed differently. Thus, I *think* the way I want to solve this problem is to call a virtual member function from within the nested base class constructor. However, this does not work, as the following example shows (compiles with MSVC 7.1)
#include <iostream>

template <typename T>
class Base
{
public:
	virtual T* foo(T* a)=0;

	class NestedBase
	{
	public:
		NestedBase(T* pData);
		~NestedBase(){delete data;}
	//protected:
		T* data;
	};


	Base(T* pData=0){pNBdata = new NestedBase(pData);}
	~Base(){delete pNBdata; pNBdata=0;}

protected:
	NestedBase*  pNBdata;

};

template <typename T>
Base<T>::NestedBase::NestedBase(T* pData)
{
	data = pData;
	T* foo(data); // this line does not work, but I want it to call derived foo from nested base class
}

template <typename T>
class Derived: public Base<T>
{
public:
	Derived(T& rData):Base<T>(&rData){}
	T* foo(T* a);
};

template <typename T>
T* Derived<T>::foo(T* a)
{
	std::cout<<"Did something"<<std::endl;
	return a;
}


int main()
{
	int x = 5;
	int y = 10;
	Derived<int>* pDeriv = new Derived<int>(x);
	return 0;
}



How can I call the derived version of foo from within the nested base class? If this is not possible, what other way can I force different constructor behaviour on the nested base class from a derived class? Any and all help is appreciated. Thanks, Timkin

Share this post


Link to post
Share on other sites
Advertisement
Your constructor for NestedBase would have to look something like this:

template <typename T>
Base<T>::NestedBase::NestedBase(T* pData, Base base)
{
data = pData;
base->foo(data);
}





But this won't work anyway since the NestedBase instance is being created in the constructor of Base, that is before Derived has been constructed (and more importantly its vtable entries). You'll have to work out an approach to achieve what you need by either calling an Init() function after the object is constructed or instantiate the NestedBase instance in the constructor of every derived class.

Share this post


Link to post
Share on other sites
wow.. That's some confusing code and I have no idea why you are wanting to do this stuff(so you may want to rethink what you are doing and see if there is a simplier way) but anyways that isn't the issue here....

If I understand your code correctly, in order to call Base::Foo from the NestedBase class. This is required:

a-) NestedBase doesn't have a pointer or anything to the Base class(or derivative) just the pointer to the data.

b-) If you gave the NestedBase class a pointer to the Base class(like passing the this pointer). You could store it and do it that way AFTER all the constructors are called. The way your code is setup now the constructor order would be like this:

Base's Constructor
NestedBase's Constructor
Derived's Constructor

AFAIK Virtual Methods won't/shouldn't work until all the constructors are called so you could called Foo until after the constructors were called.

Share this post


Link to post
Share on other sites
Ah... of course... I hadn't considered construction order. Thanks guys.

To answer the: 'why am I doing this' thought...

Base is a tree management class. The nested class is a tree class and its constructor builds an entire tree in a neat, recursive, funky manner given the template data. However, there are many different sorts of trees that can be built for any given data type and thus, I want derived classes that use a common interface to a) generate specialised tree types governed by the derived class; and, b) specialise the access methods to the tree depending on what sort of tree it is. I had wanted to do this within object creation and so I had constructed the above heirarchy. However, unless I start bastardising the creation process, the better way would probably be to accept the lesser method of using an Init() function (which requires two lines of code to generate a new tree, as opposed to one). This isn't a huge overhead... it just makes the use of these trees a little more error prone, since you have to create the handler and then initialise the tree.


As for that being confusing code... why do you say that (ignoring the fact that I didn't bother to document it because its a trivially simple example).

Cheers,

Timkin

Share this post


Link to post
Share on other sites
Oh yeah, not sure if you realise this but a nested class isn't associated with an instance of the nesting class. The only relation is that the class is a member and can therefore see private and protected members of the nesting class.

Share this post


Link to post
Share on other sites
It's generally not a good idea to call virtual functions from base constructors because the derived class hasn't been constructed yet.

Share this post


Link to post
Share on other sites
Quote:
Original post by joanusdmentia
Oh yeah, not sure if you realise this but a nested class isn't associated with an instance of the nesting class. The only relation is that the class is a member and can therefore see private and protected members of the nesting class.


(Edited... I misread this and the subsequent post by the AP made me realise my mistake)...

What I want is that the nested class be hidden by the base class. The base class should be able to access the private and protected members of the nested class. As I understand it, this is the usual use of nested classes.

Timkin

[Edited by - Timkin on September 26, 2004 10:55:40 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by joanusdmentia
Oh yeah, not sure if you realise this but a nested class isn't associated with an instance of the nesting class. The only relation is that the class is a member and can therefore see private and protected members of the nesting class.


If you mean that NestedBase can access/see private and protected members in Base, then that's wrong. As it stands right now, it's not in the C++ standard. It's beying proposed as an amendment. So, use it at you own risk, since some of the compiler will allow and some of them will not.

For reference see:
C/C++ User Journal, October 2004, "Frinedly Nesting" article by Herb Sutter and Jim Hyslop.

Share this post


Link to post
Share on other sites
Quote:
Original post by Timkin
What I want is that the nested class be hidden by the base class. The base class should be able to access the private and protected members of the nested class. As I understand it, this is the usual use of nested classes.

As far as I know a class cannot access the protected and private members of a nested class, I just double checked in gcc 3.2 and it didn't work with that. Not sure what the standard says though.

Quote:
If you mean that NestedBase can access/see private and protected members in Base, then that's wrong. As it stands right now, it's not in the C++ standard. It's beying proposed as an amendment. So, use it at you own risk, since some of the compiler will allow and some of them will not.

Hmm, didn't realize that. I've used it a couple of times without any problems with both vc++ and gcc, so I'd say it's still relatively safe to use, but no, not guarentteed.

Share this post


Link to post
Share on other sites
Quote:

As for that being confusing code... why do you say that (ignoring the fact that I didn't bother to document it because its a trivially simple example).


I guess it was just because I was tired and wondering what you were using it for. Also since it's in a webbrowser and all the classes are together.

oh, and thanks for the explanation as to the why.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!