开发者

C++ Inheritance Issue

I am using code::blocks, with, I believe gcc. Given the example code (this is pseudo code and may not replicate the problem):

//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();}//
};

I would get similar compile errors, like: Error: 'A' not declared in this scope. Error: Function1() not declared in this scope.

I was under the impression that all base variables and functions were inherited to the subclass. Given the base class has a lot of functions and variables, I don't want to use the 'using' keyword as I'd have to declare it for every function and variable (to my knowledge).

Is there any way to make it so TestB explicitly or actually includes the stuff it's inheriting?

Relevant snippets below

Okay. It's not possible to include example code as it's in project, but I will quote the key snippets:

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

The line this is on is:

if(!Array.SetToSize(Size))

The class it's in is:

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

And the incriminating line from TemplateList is:

SIZE_TYPE Size; //SIZE_TYPE is unsigned long.
//开发者_StackOverflow社区SIZE_TYPE is available in all files as unsigned long.

Files go: TemplateList.h->TemplateBasics.h->TemplateListAdv.h

No missing files from what I can see.

I will tack in, the 'using' keyword resolves it individually, but this has been bugging me as I thought inheritance was automatic.

Compiler data as requested:

"Release 10.05 rev 6283 (2010-05-27 09:09:13) gcc 4.4.1 Windows/unicode - 32 bit"


So it looks like you are getting error wite template classes inheritance, isn't it? They are a big difference comparing to non-template ones. Assuming you have code like this:


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();}//
};

The issue is caused by two-phase name lookup. All members of the base TestA class are dependent names, i.e. they depend on the template argument T. This is so because you can have template specialization for TestA with totally different members, e.g.:


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

Now, there is no A and Function1 members in the TestA, so they would be unaccessible in TestB as well. In order to let compiler know that these members are indeed depende on the template argument you should write TestB like this:


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

This way you make compiler resolve names only during template instantiation time instead of template declaration time and it will known about base class members.

One thing to add is that there is no such issue with VC compiler, it doesn't try to parse templates until instantiation and thus don't support two-phase name lookup.


The problem that you're having about accessing base class stuff in a class template, is a FAQ item.

Rather then quoting the whole FAQ item here, I just link to it: that's your answer.

The code that you presented to illustrate the problem was unrelated, sorry. It is always a good idea to give an actual example rather than an example of what one thinks might be the problem.

Cheers & hth.,


The problem is that you are using templates, and the base class is a 'dependent name'. That is, the template base class could be specialized and not have the Size member, the compiler just doesn't know when it compiles your class, because the Size reference is not in a dependent context.

In your particular case the easiest solution is to refer to the inherited members using this:

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

And since this is a dependent name, it should work


Are you sure that :

  • Size is a protected or public attribute of TemplateList ?

  • you're not calling if(!Array.SetToSize(Size)) from a static method ?


The question is really bad, and you might want to improve on that. Anyway, my crystal ball tells me that Size is defined in a base template, and that because the identifier Size is not dependent lookup is not going into the base template and the compiler not seeing it. Add a this-> before Size and you should be set.


When interpreting a template member function, the compiler must (following the standard) decide for each symbol if it is dependent on the template parameter. If it is dependent on it, then it'll only be resolved when the template is instantiated. However, he must resolve it at this moment.

In your case, the compiler think that A and Function1 don't depend on the template parameter and should thus be resolvable just after the parse. You just have to make it depend on the template parameter by using this->A and this->Function1

So, you should have something like that.

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();
  }
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜