Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jan 11th, 2008, 3:56 AM   #1
Lakrids
Newbie
 
Join Date: Dec 2007
Posts: 28
Rep Power: 0 Lakrids is on a distinguished road
Friends in inheritance

Hello,

There is a rather annoying problem in my code, and I just can't get to the bottom of it. I have a class, A, and another one, B, which inherits from A. Now, A has a friend class, C, which is declared inside it.

Whenever I want to use C's public constructor from within a method of B, I get errors like "expected type-specifier", and "expected ';'".

I know friends are not inherited, so I made C a friend of B, too. Which changes absolutely nothing. Always the same errors. What am I doing wrong? If I call C's constructor like : A::C(...), or simply C(...), I get the same errors.

Have any ideas?

Thanks
Lakrids is offline   Reply With Quote
Old Jan 11th, 2008, 4:29 AM   #2
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5 grumpy is on a distinguished road
Re: Friends in inheritance

My guess, not having seen code that illustrates the problem, is that you've left out a semi-colon or a closing brace somewhere in code before where the error is reported.

Or - less likely - you're working with template classes, for which the rules are slightly different, and you've left out a "typename" keyword at a point where you need it.
grumpy is offline   Reply With Quote
Old Jan 11th, 2008, 4:45 AM   #3
Lakrids
Newbie
 
Join Date: Dec 2007
Posts: 28
Rep Power: 0 Lakrids is on a distinguished road
Re: Friends in inheritance

Nice guess, I AM working with template classes. OK, here's the simplified code to illustrate what is happening :

cplusplus Syntax (Toggle Plain Text)
  1. template <typename T> class A {
  2. protected :
  3. class C;
  4. public :
  5. ...code...
  6. };
  7.  
  8. template <typename T> class A<T>::C {
  9. friend class A;
  10. public:
  11. C(...params...);
  12. };
  13.  
  14.  
  15. template <typename T> class B : public A<T> {
  16. int var;
  17. method1(...);
  18. ...
  19. };

Now, here's the problem :

cplusplus Syntax (Toggle Plain Text)
  1. template <typename T> B<T>::method1(...) {
  2. this->var = C(...);
  3. }

generates errors.

So does :

cplusplus Syntax (Toggle Plain Text)
  1. template <typename T> B<T>::method1(...) {
  2. this->var = A<T>::C(...);
  3. }

EVEN IF, before declaring the class A, I declare B like so :

cplusplus Syntax (Toggle Plain Text)
  1. template <typename T> class B;

and put, in class C :

cplusplus Syntax (Toggle Plain Text)
  1. friend class B<T>;

When using method1, I get the same errors.

What should I do? How can B access C's constructor?
Lakrids is offline   Reply With Quote
Old Jan 11th, 2008, 5:33 AM   #4
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5 grumpy is on a distinguished road
Re: Friends in inheritance

It is usually better if you provide a SMALL but COMPLETE code sample that illustrates your problem. By paraphrasing, as you've done, you force people to guess at your problem because you may have left out key details.

My primary guess is that you've encountered one of the obscure limitations with templates in the current C++ standard -- fixing it is on the list of proposals for a future version of the standard. To make use of A<T>::C within a member function of B<T> you need to implement the member function inline (i.e. within the declaration of B<T>). For example;
template <typename T> class B : public A<T> {
public:
   int var;
   void method() {A<T>::C  x;  var = x;};    // assumes A<T>::C can be implicitly converted to int
};
The second problem I can see is this snippet of yours which (even ignoring the fact it is not within the class declaration);
 template <typename T> B<T>::method1(...) {
      this->var = A<T>::C(...);
 }
can actually look like a function call to the compiler (a call of a function that doesn't exist, hence a compiler error). Since you've paraphrased your code (rather than providing actual code) I can't exclude this possibility.

But, in any event, the problem has nothing to do with friendship (friendship affects accessibility, not the sort of thing you're seeing).

Without an actual code sample that illustrates your problem, I can't/won't guess further.
grumpy is offline   Reply With Quote
Old Jan 11th, 2008, 6:07 AM   #5
Lakrids
Newbie
 
Join Date: Dec 2007
Posts: 28
Rep Power: 0 Lakrids is on a distinguished road
Re: Friends in inheritance

First of all, thank you for your help.

Second, here is the actual code :

cplusplus Syntax (Toggle Plain Text)
  1. // Class "A"
  2. template <typename T> class LinkedList {
  3. protected:
  4. class Element;
  5. Element *headOfList;
  6. public:
  7. <constructor, destructor, and other methods>
  8. };
  9.  
  10.  
  11. // Class "C"
  12. template <typename T> class LinkedList<T>::Element {
  13. protected:
  14. friend class LinkedList;
  15. int info;
  16. public:
  17. Element (int info=0, const LinkedList& next); // constructor
  18. };
  19.  
  20.  
  21. // Class "B"
  22. template <typename T> class DerivedList : public LinkedList<T> {
  23.  
  24. public:
  25. ...
  26. // The actual method I was talking about is a "conversion constructor"
  27. explicit DerivedList(const LinkedList<T>& );
  28. ...
  29. };
  30.  
  31. // The actual definition of the method :
  32. template <typename T> DerivedList<T>::DerivedList(const LinkedList<T>& list) {
  33. this->headOfList = new Element(*list.headOfList);
  34. }

generates the following errors at 'new Element" :
error : expected type-specifier before 'Element'

And if I write :

cplusplus Syntax (Toggle Plain Text)
  1. this->headOfList = new LinkedList<T>::Element(*list.headOfList);

i get:
error : expected type-specifier

So, my idea was to put

cplusplus Syntax (Toggle Plain Text)
  1. friend class DerivedList<T>

inside the class Element, and declaring DerivedList before LinkedList like so :

cplusplus Syntax (Toggle Plain Text)
  1. template <typename T> class DerivedList;

and the compiler gives the very same errors as before.

What do you think?
Lakrids is offline   Reply With Quote
Old Jan 11th, 2008, 4:42 PM   #6
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,223
Rep Power: 5 grumpy is on a distinguished road
Re: Friends in inheritance

Yep; you're running into the issue of dependant template types (instantiation of DerivedList template relies on instantiation of the LinkedList template, .... etc and the compiler is allowed to defer instantiation of any of those templates until it is too late).

In your particular case, a workaround I suggest is providing a copy constructor for LinkedList<> with the same body as your current DerivedList<> copy constructor, and not explicitly implement the DerivedList copy constructor. (the compiler generated copy constructor for DerivedList would automatically invoke the inherited one).

Other than that, you need to inline ALL your definitions (no reliance on forward declaration of the Element class, no "out of line" implementation of copy constructors, etc). The philosophy is making sure that the compiler has access to all information it needs when .... eventually ... it finds it needs to instantiate templates.

Friend declarations are not a solution to the problem: they just influence what code is allowed to access something. If it was, you could just make everything public and the problem would go away.

More generically (C++ template issues aside) I'm failing to work out how your design makes sense for a linked list. Your LinkedList contains a pointer to an element, and presumably each element needs a pointer to the LinkedList that contains it. That circular dependancy does not make sense to me. Generally I would expect the nodes of a linked list (your Element) would contain data (the info member), and one or more pointers to other nodes. No need for a pointer back to the containing LinkedList.

Practically, I'd also use a std::list<> anyway, rather than rolling my own linked list template as well. I assume you're doing this for learning purposes.
grumpy is offline   Reply With Quote
Old Jan 12th, 2008, 3:42 AM   #7
Lakrids
Newbie
 
Join Date: Dec 2007
Posts: 28
Rep Power: 0 Lakrids is on a distinguished road
Re: Friends in inheritance

Thank you ever so much for these tips.

As for your remarks about the implementation of the list, I agree with you. This code is not mine, it is given by an educator, who wants us to further enhance it. I know there are many much simpler ways (and more clearer ways) to implement a linked list, the aim of this exercise was to make us familiar with friends in inheritance. But you are absolutely right : this code is not efficient at all, and moreover, it is very unclear.

Having said this, I thank you once more for outlining what should and should not be done when using template classes like this...so much I didn't know.
Lakrids is offline   Reply With Quote
Old Jan 12th, 2008, 8:30 AM   #8
Jessehk
The Oblivious One
 
Jessehk's Avatar
 
Join Date: May 2005
Location: Ontario, Canada
Posts: 644
Rep Power: 4 Jessehk is on a distinguished road
Re: Friends in inheritance

I was playing around with writing data structures in C++ a while ago. I hope this is somewhat useful.

c++ Syntax (Toggle Plain Text)
  1. #include <iostream>
  2.  
  3. template <typename T>
  4. class ListNode {
  5. private:
  6. T data_;
  7. ListNode<T> *next_;
  8. public:
  9. explicit ListNode( const T &data, ListNode<T> *next=0 ) :
  10. data_( data ),
  11. next_( next ) {}
  12.  
  13. const T &data() const { return data_; }
  14. void setData( const T &newData ) { data_ = newData; }
  15.  
  16. ListNode<T> *next() { return next_; }
  17. void setNext( ListNode<T> *newNext ) { next_ = newNext; }
  18.  
  19. ~ListNode() {
  20. delete next_;
  21. }
  22. };
  23.  
  24. template <typename T>
  25. class List {
  26. private:
  27. ListNode<T> *head_;
  28. public:
  29. typedef ListNode<T> *iterator;
  30.  
  31. explicit List() :
  32. head_( 0 ) {}
  33.  
  34. void append( const T &data ) {
  35. if ( head_ == 0 )
  36. head_ = new ListNode<T>( data );
  37. else {
  38. iterator iter = head_;
  39.  
  40. while ( iter->next() != 0 )
  41. iter = iter->next();
  42.  
  43. iter->setNext( new ListNode<T>( data ) );
  44. }
  45. }
  46.  
  47. iterator begin() { return head_; }
  48. iterator end() { return 0; }
  49.  
  50. ~List() {
  51. delete head_;
  52. }
  53. };
  54.  
  55. int main() {
  56. List<int> numbs;
  57.  
  58. for ( int x( 0 ); x != 10; ++x )
  59. numbs.append( x + 1 );
  60.  
  61. List<int>::iterator iter = numbs.begin();
  62. for (; iter != numbs.end(); iter = iter->next() )
  63. std::cout << iter->data() << std::endl;
  64. }
__________________
Dr. Zoidberg: [ecstatic] I'm going to a movie... with FRIENDS!
Jessehk is offline   Reply With Quote
Old Jan 12th, 2008, 11:06 AM   #9
Lakrids
Newbie
 
Join Date: Dec 2007
Posts: 28
Rep Power: 0 Lakrids is on a distinguished road
Re: Friends in inheritance

Wow thanks! I'm sure I'll be able to put it to use!
Lakrids is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Weird inheritance problem Lakrids C++ 2 Dec 23rd, 2007 6:24 AM
Inheritance and Object-Oriented Information Systems emdiesse Coder's Corner Lounge 1 Apr 24th, 2007 10:45 AM
Not class inheritance Writlaus C++ 3 Sep 2nd, 2006 7:44 PM
Reverse Inheritance Darkhack C# 3 Jan 16th, 2006 5:05 PM
Hello my (I Hope) Friends Justin Case Community Introductions 16 Sep 16th, 2005 4:08 AM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 11:28 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC