samedi 19 avril 2014

modèles - variable virtual C++ dans la hiérarchie d'héritage de classe - Stack Overflow


I have a template class hierarchy,


                   ___ Class (ClassA)
|
AbstractClass_____

|___ Class (ClassB)

in classA and ClassB, I have a const NullPosition of a templated type, which is different in ClassA and ClassB. In class classA and ClassB I have to do some operation which are dependant on the value of the NullPosition.


Now I need to do some operations depending on the value on NullPosition, but I am having hard time since the variable are different type and values. To be more specific NullPosition in classA identifies an invalid array index, therefore equals -1; in classB it identifies a NULL pointer therefore it equals 0.


Please find below an example.


#ifndef ABSTRACTCLASS_H
#define ABSTRACTCLASS_H

template <class T, class P>
class AbstractClass
{
public:

typedef T Type;
typedef P Position;

void MethodX() const;
virtual Position Method() const = 0;


};

template <class T, class P>
void AbstractClass<T,P>::MethodX() const
{
Position p=Method();

/*
what I am trying to achieve is being able to use the constant NullPosition in abstract class.

if (p==NullPosition)
cout<<"p is equal NULLPOSITION";
else
cout<<"p is not equal NULLPOSITION";
*/
}

#endif



#ifndef CLASS_A_H
#define CLASS_A_H
#include "../AbstractClass.h"

template <class T>
class Class:public AbstractClass<T,unsigned int>
{
public:

typedef T Type;
typedef typename AbstractClass<T,unsigned int>::Position Position;

Class();

Position Method() const;

static const Position NullPosition=-1;

private:
Type* TypeArray;
unsigned int nElements;

};

template <class T>
Class<T>::Class()
{
nElements=0;
TypeArray=new Type[128];
}

template <class T>
typename Class<T>::Position Class<T>::Method() const
{

return NullPosition;

}

#endif




#ifndef CLASS_B_H
#define CLASS_B_H

#include "../AbstractClass.h"

template <class T>
struct elementNode
{
typedef T Type;
typedef elementNode* Position;

Type element;
Position nextNode;
};

template <class T>
class Class:public AbstractClass<T, typename elementNode<T>::Position>
{
public:

typedef T Type;
typedef typename AbstractClass<T, typename elementNode<T>::Position>::Position Position;

Class();
Position Method() const;

static const Position NullPosition;

private:
Position root;
Position lastElement;

};

template <class T>
const typename Class<T>::Position Class<T>::NullPosition=0;

template <class T>
Class<T>::Class()
{
lastElement=root=NullPosition;
}

template <class T>
typename Class<T>::Position Class<T>::Method() const
{

return NullPosition;

}

#endif


#include <cstdlib>
#include <iostream>

using namespace std;


#include "Class/ClassA/Class.h"

int main(int argc, char *argv[])
{
Class<int> classA;

classA.MethodX();

system("PAUSE");
return EXIT_SUCCESS;
}

Please not that ClassA and ClassB share the same name Class, so that I a can use them interchangeble in my code by changing just the include path - #include "Class/ClassA/Class.h" for classA and #include "Class/ClassB/Class.h" for classB.




I don't see the problem. You have so many choices:



  • Pass NullPosition as a non-type template argument along to the base class.

  • Create a traits class that determines the null position for some type. Specialize it before defining the subclasses.

  • Add an abstract function to the base class that the subclasses override to return the null position.

  • Add an abstract function to the base class that the subclasses override to determine whether a position is the NullPosition.




I am not sure if I understand the entire requirement, but it appears you are trying to do something different on MethodX depending on the type of P.


You could use template specialization on the MethodX function etc. since the second parameter P is different for the two derived classes.


Something like this:


template<class T> void MethodX<T,NullPosition>
{
// Do NullPosition stuff here
}



Maybe there is something i didn't understand, but if you need a member in the parent class, then why put it in the subclass and not the parent?


Oh, and if you have two classes with same name but different method implementations, only one of the methods will exist after linking. If you want to access both classes using a common name in different source files, use typedefs:


class foo1 {.....};
class foo2 {.....};

typedef foo foo1;
// or typedef foo foo2;


I have a template class hierarchy,


                   ___ Class (ClassA)
|
AbstractClass_____

|___ Class (ClassB)

in classA and ClassB, I have a const NullPosition of a templated type, which is different in ClassA and ClassB. In class classA and ClassB I have to do some operation which are dependant on the value of the NullPosition.


Now I need to do some operations depending on the value on NullPosition, but I am having hard time since the variable are different type and values. To be more specific NullPosition in classA identifies an invalid array index, therefore equals -1; in classB it identifies a NULL pointer therefore it equals 0.


Please find below an example.


#ifndef ABSTRACTCLASS_H
#define ABSTRACTCLASS_H

template <class T, class P>
class AbstractClass
{
public:

typedef T Type;
typedef P Position;

void MethodX() const;
virtual Position Method() const = 0;


};

template <class T, class P>
void AbstractClass<T,P>::MethodX() const
{
Position p=Method();

/*
what I am trying to achieve is being able to use the constant NullPosition in abstract class.

if (p==NullPosition)
cout<<"p is equal NULLPOSITION";
else
cout<<"p is not equal NULLPOSITION";
*/
}

#endif



#ifndef CLASS_A_H
#define CLASS_A_H
#include "../AbstractClass.h"

template <class T>
class Class:public AbstractClass<T,unsigned int>
{
public:

typedef T Type;
typedef typename AbstractClass<T,unsigned int>::Position Position;

Class();

Position Method() const;

static const Position NullPosition=-1;

private:
Type* TypeArray;
unsigned int nElements;

};

template <class T>
Class<T>::Class()
{
nElements=0;
TypeArray=new Type[128];
}

template <class T>
typename Class<T>::Position Class<T>::Method() const
{

return NullPosition;

}

#endif




#ifndef CLASS_B_H
#define CLASS_B_H

#include "../AbstractClass.h"

template <class T>
struct elementNode
{
typedef T Type;
typedef elementNode* Position;

Type element;
Position nextNode;
};

template <class T>
class Class:public AbstractClass<T, typename elementNode<T>::Position>
{
public:

typedef T Type;
typedef typename AbstractClass<T, typename elementNode<T>::Position>::Position Position;

Class();
Position Method() const;

static const Position NullPosition;

private:
Position root;
Position lastElement;

};

template <class T>
const typename Class<T>::Position Class<T>::NullPosition=0;

template <class T>
Class<T>::Class()
{
lastElement=root=NullPosition;
}

template <class T>
typename Class<T>::Position Class<T>::Method() const
{

return NullPosition;

}

#endif


#include <cstdlib>
#include <iostream>

using namespace std;


#include "Class/ClassA/Class.h"

int main(int argc, char *argv[])
{
Class<int> classA;

classA.MethodX();

system("PAUSE");
return EXIT_SUCCESS;
}

Please not that ClassA and ClassB share the same name Class, so that I a can use them interchangeble in my code by changing just the include path - #include "Class/ClassA/Class.h" for classA and #include "Class/ClassB/Class.h" for classB.



I don't see the problem. You have so many choices:



  • Pass NullPosition as a non-type template argument along to the base class.

  • Create a traits class that determines the null position for some type. Specialize it before defining the subclasses.

  • Add an abstract function to the base class that the subclasses override to return the null position.

  • Add an abstract function to the base class that the subclasses override to determine whether a position is the NullPosition.



I am not sure if I understand the entire requirement, but it appears you are trying to do something different on MethodX depending on the type of P.


You could use template specialization on the MethodX function etc. since the second parameter P is different for the two derived classes.


Something like this:


template<class T> void MethodX<T,NullPosition>
{
// Do NullPosition stuff here
}


Maybe there is something i didn't understand, but if you need a member in the parent class, then why put it in the subclass and not the parent?


Oh, and if you have two classes with same name but different method implementations, only one of the methods will exist after linking. If you want to access both classes using a common name in different source files, use typedefs:


class foo1 {.....};
class foo2 {.....};

typedef foo foo1;
// or typedef foo foo2;

0 commentaires:

Enregistrer un commentaire