Проблема наследования C ++ - PullRequest
       3

Проблема наследования C ++

0 голосов
/ 08 сентября 2011

Я использую code :: blocks, с, я полагаю, gcc.Учитывая пример кода (это псевдокод и может не повторять проблему):

//Assume this is in a separate header file to B
class TestA
{
    protected:
        int A;

    public:
        void Function1(){A = 0;}
};

class TestB : public TestA
{
    public:
        void CallFunction(){ A = 10; Function1();}//
};

Я получу похожие ошибки компиляции, например: Ошибка: 'A' не объявлено в этой области.Ошибка: Function1 () не объявлена ​​в этой области.

У меня сложилось впечатление, что все базовые переменные и функции были унаследованы для подкласса.Учитывая, что в базовом классе много функций и переменных, я не хочу использовать ключевое слово «using», так как я должен был бы объявить его для каждой функции и переменной (насколько мне известно).

IsЕсть ли способ сделать так, чтобы TestB явно или фактически включал в себя материал, который он наследовал?

Соответствующие фрагменты ниже

Хорошо.Невозможно включить пример кода, как он есть в проекте, но я процитирую фрагменты ключа:

C:\Users\user\Desktop\Projects\RND2\TemplateListAdv.h|30|error: 'Size' was not declared in this scope|

Строка, в которой он находится:

if(!Array.SetToSize(Size))

Класс, в котором он находится,:

template<typename TemplateItem>
class TemplateListAdv : public TemplateList<TemplateItem>

И инкриминирующая строка из TemplateList:

SIZE_TYPE Size; //SIZE_TYPE is unsigned long.
//SIZE_TYPE is available in all files as unsigned long.

Файлы идут: TemplateList.h-> TemplateBasics.h-> TemplateListAdv.h

Нетпропущенные файлы из того, что я вижу.

Я добавлю, ключевое слово 'using' разрешает его индивидуально, но меня это беспокоило, так как я думал, что наследование было автоматическим.

Данные компилятора какзапрошено:

"Выпуск 10.05 rev 6283 (2010-05-27 09:09:13) gcc 4.4.1 Windows / Unicode - 32 bit"

Ответы [ 6 ]

2 голосов
/ 08 сентября 2011

Похоже, вы получаете ошибку наследования классов шаблона, не так ли?Это большая разница по сравнению с не шаблонными.Предполагая, что у вас есть такой код:


template <class T>
class TestA
{
    protected:
        int A;

    public:
        void Function1(){A = 0;}
};

template <class T>
class TestB : public TestA<T>
{
    public:
        void CallFunction(){ A = 10; Function1();}//
};

Проблема вызвана двухфазным поиском имени .Все члены базового класса TestA являются зависимыми именами , то есть они зависят от аргумента шаблона T. Это так, потому что вы можете иметь специализацию шаблона для TestA с совершенно разными членами, например:


template <class T>
class TestA
{
    protected:
        int A;

    public:
        void Function1(){A = 0;}
};

template <class T>
class TestB : public TestA<T>
{
    public:
        void CallFunction(){ A = 10; Function1();}//
};

template <>
class TestA<int>
{
};

Теперь в TestA нет членов A и Function1, поэтому они также будут недоступны в TestB.Чтобы компилятор знал, что эти члены действительно зависят от аргумента шаблона, вы должны написать TestB следующим образом:


template <class T>
class TestB : public TestA<T>
{
    public:
        void CallFunction(){ <strong>this-></strong>A = 10; <strong>this-></strong>Function1();}//
};

Таким образом, вы заставите компилятор разрешать имена только во время создания шаблона вместо времени объявления шаблона ион будет знать о членах базового класса.

Одна вещь, которую нужно добавить, заключается в том, что такой проблемы нет с компилятором VC, он не пытается анализировать шаблоны до момента его создания и, следовательно, не поддерживает двухфазный поиск имен.

1 голос
/ 08 сентября 2011

При интерпретации функции-члена шаблона компилятор должен (следуя стандарту) решить для каждого символа, зависит ли он от параметра шаблона. Если он зависит от него, то он будет разрешен только при создании экземпляра шаблона. Тем не менее, он должен решить это в данный момент.

В вашем случае компилятор считает, что A и Function1 не зависят от параметра шаблона и поэтому должны быть разрешены сразу после разбора. Вам просто нужно сделать так, чтобы он зависел от параметра шаблона, используя this->A и this->Function1

Итак, у вас должно быть что-то подобное.

template < typename T >
class Base
{
protected:
  int A;

public:
  void Function1() { A = 0; }
};

template < typename T >
class Derived : public Base< T >
{
public:
  void CallFunction1() {
    this->A = 10;
    this->Function1();
  }
};
1 голос
/ 08 сентября 2011

Вопрос действительно плохой, и вы можете улучшить его. В любом случае, мой хрустальный шар говорит мне, что Size определено в базовом шаблоне, и что, поскольку идентификатор Size не зависит *, поиск 1004 * не входит в базовый шаблон, а компилятор его не видит. Добавьте this-> перед Size, и вы должны быть установлены.

1 голос
/ 08 сентября 2011

Вы уверены, что:

  • Размер является защищенным или открытым атрибутом TemplateList?

  • вы не вызываете if (! Array.SetToSize (Size)) из статического метода?

1 голос
/ 08 сентября 2011

Проблема в том, что вы используете шаблоны, а базовый класс является «зависимым именем».То есть базовый класс шаблона может быть специализированным и не иметь члена Size, компилятор просто не знает, когда он компилирует ваш класс, потому что ссылка Size не находится в зависимом контексте.

ВВ вашем конкретном случае самое простое решение - обратиться к унаследованным элементам, используя this:

if(!Array.SetToSize(this->Size))

. И поскольку this является зависимым именем, оно должно работать

1 голос
/ 08 сентября 2011

Проблема с доступом к материалам базового класса в классе template заключается в элементе FAQ .

Вместо того, чтобы цитировать весь элемент FAQздесь я просто ссылаюсь на него: вот ваш ответ.

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

Приветствия & hth.,

...