WedX - журнал о программировании и компьютерных науках

Виртуальная переменная C++ в иерархии классов наследования

У меня есть иерархия классов шаблонов,

                   ___ Class (ClassA)
                  |
AbstractClass_____

                  |___ Class (ClassB)

в classA и ClassB у меня есть const NullPosition шаблонного типа, который отличается в ClassA и ClassB. В классах classA и ClassB мне нужно выполнить некоторую операцию, которая зависит от значения NullPosition.

Теперь мне нужно выполнить некоторые операции в зависимости от значения NullPosition, но мне трудно, так как переменная имеет другой тип и значения. Чтобы быть более конкретным, NullPosition в classA идентифицирует недопустимый индекс массива, поэтому равен -1; в классе B он идентифицирует указатель NULL, поэтому он равен 0.

Пожалуйста, найдите ниже пример.

#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;
}

Обратите внимание, что ClassA и ClassB имеют одно и то же имя Class, чтобы я мог использовать их взаимозаменяемо в своем коде, изменив только путь включения - #include "Class/ClassA/Class.h" для classA и #include "Class/ClassB" /Класс.h" для класса B.


  • У меня одного по спине побежали мурашки после прочтения заключительного абзаца? 27.08.2013
  • У меня много вопросов о некоторых решениях, которые вы сделали, которые, кажется, делают это еще более запутанным. Почему бы не использовать template <class Type, class Position> вместо typedef T Type. 27.08.2013
  • Имена аргументов шаблона недоступны в подклассах. 27.08.2013
  • Чтобы добавить некоторый контекст к дрожи WhozCraig: зачем вам делать что-то подобное? Вы уже можете использовать их взаимозаменяемо, не включая ерунду, используя указатель на их базовый класс, по крайней мере, если они оба являются производными от некоторого AbstractClass‹T,P›. Если ClassA и ClassB (т. е. наиболее производные типы) различны, но все же могут использоваться взаимозаменяемо, вы можете проверить, не имеет ли ваш дизайн недостатков, или обеспечить преобразование. В противном случае, если вам нужен ClassA, используйте ClassA, если вам нужен ClassB, используйте ClassB. Использование одного и того же имени для разных типов невероятно вредно. 27.08.2013

Ответы:


1

Я не вижу проблемы. У вас так много вариантов:

  • Передайте NullPosition в качестве аргумента шаблона, отличного от типа, вместе с базовым классом.
  • Создайте класс свойств, который определяет нулевую позицию для некоторого типа. Специализируйте его перед определением подклассов.
  • Добавьте в базовый класс абстрактную функцию, которую подклассы переопределяют, чтобы возвращать нулевую позицию.
  • Добавьте в базовый класс абстрактную функцию, которую подклассы переопределяют, чтобы определить, является ли позиция NullPosition.
27.08.2013

2

Я не уверен, что понимаю все требования, но, похоже, вы пытаетесь сделать что-то другое в MethodX в зависимости от типа P.

Вы можете использовать специализацию шаблона для функции MethodX и т. д., поскольку второй параметр P отличается для двух производных классов.

Что-то вроде этого:

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

3

Может быть, я чего-то не понял, но если вам нужен член в родительском классе, то зачем помещать его в подкласс, а не в родителя?

Да, и если у вас есть два класса с одинаковым именем, но разными реализациями методов, после связывания будет существовать только один из методов. Если вы хотите получить доступ к обоим классам, используя общее имя в разных исходных файлах, используйте typedefs:

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

typedef foo foo1;
// or typedef foo foo2;
27.08.2013
Новые материалы

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

Учебные заметки: создание моего первого пакета Node.js
Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

ИИ в аэрокосмической отрасли
Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


Для любых предложений по сайту: [email protected]