2011-07-06 32 views
23

Tôi có 4 file sau được thừa hưởng:mẫu: các biến thành viên lớp cha không hiển thị trong lớp

  1. arrayListType.h: Khai báo và định nghĩa arrayListType lớp làm mẫu
  2. unorderedArrayListType.h: Kế thừa từ arrayListType lớp và Khai báo và định nghĩa unorderedArrayListType làm mẫu.
  3. main1.cpp: Chương trình thử nghiệm để kiểm tra unorderedArrayListType lớp học.
  4. Makefile

tôi nhận được một lỗi biên dịch nói khi truy cập vào các biến bảo vệ của arrayListType trong unorderedArrayListType ví dụ: "chiều dài không được kê khai trong phạm vi này", "danh sách không được kê khai trong phạm vi này", trong đó chiều dài và danh sách là các biến được bảo vệ trong lớp arrayListType.

Sau đây là các mã:
arrayListType.h

#ifndef H_arrayListType 
#define H_arrayListType 

#include <iostream> 

using namespace std; 

template <class elemType> 
class arrayListType 
{ 

public: 

    const arrayListType<elemType>&operator=(const arrayListType<elemType>&); 

    bool isEmpty() const; 
    bool isFull() const; 
    int listSize() const; 
    int maxListSize() const; 
    void print() const; 
    bool isItemAtEqual(int location, const elemType& item) const; 
    virtual void insertAt(int location, const elemType& insertItem) = 0; 
    virtual void insertEnd(const elemType& insertItem) = 0; 
    void removeAt(int location); 
    void retrieveAt(int location, elemType& retItem) const; 
    virtual void replaceAt(int location, const elemType& repItem) = 0; 
    void clearList(); 
    virtual int seqSearch(const elemType& searchItem) const; 
    virtual void remove(const elemType& removeItem) = 0; 

    arrayListType(int size = 100); 
    arrayListType(const arrayListType<elemType>& otherList); 

    virtual ~arrayListType(); 


protected: 

    elemType *list; 
    int length; 
    int maxSize; 
}; 


template <class elemType> 
bool arrayListType<elemType>::isEmpty() const 
{ 
    return (length == 0); 
} 

// remaining non-virtual functions of arrayListType class 

#endif 

unorderedArrayListType.h

#ifndef H_unorderedArrayListType 
#define H_unorderedArrayListType 

//#include <iostream> 
#include "arrayListType.h" 

//using namespace std; 

template <class elemType> 
class unorderedArrayListType: public arrayListType<elemType> 
{ 

public: 

    void insertAt(int location, const elemType& insertItem); 
    void insertEnd(const elemType& insertItem); 
    void replaceAt(int location, const elemType& repItem); 
    int seqSearch(const elemType& searchItem) const; 
    void remove(const elemType& removeItem); 

    unorderedArrayListType(int size = 100); 
}; 

template <class elemType> 
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem) 
{ 
    for(int i = length; i > location; i--) 
     list[i] = list[i - 1]; 

    list[location] = insertItem; 
    length++; 
} 

// Remaining virtual functions that need to be defined by the inherited class 

#endif 

main1.cpp

#include <iostream> 
#include "unorderedArrayListType.h" 

using namespace std; 


int main() 
{ 
    unorderedArrayListType<int> intList(25); 

    int number; 
    cout<<"Line 3: Enter 8 integers: "; 

    for(int count = 0; count < 8; count++) 
    { 
     cin>>number; 
     intList.insertEnd(number); 
    } 

    cout<<"Line 8: intList: "; 
    intList.print(); 
    cout<<endl; 
} 

Makefile:

all: main1 


main1.o: main1.cpp 
    g++ -c -Wall main1.cpp 

main1: main1.o 
    g++ -Wall main1.o -o main 


clean: 
    rm -f *.o *~ main1 

Sau đây là lỗi biên dịch:

make 
g++ -c -Wall main1.cpp 
In file included from main1.cpp:2: 
unorderedArrayListType.h: In member function 'void unorderedArrayListType<elemType>::insertAt(int, const elemType&)': 
unorderedArrayListType.h:30: error: 'length' was not declared in this scope 
unorderedArrayListType.h:31: error: 'list' was not declared in this scope 
unorderedArrayListType.h:33: error: 'list' was not declared in this scope 

Nhiều chức năng của unorderedArrayListType biến được liệt kê và được bảo vệ chỉ ra như không khai báo trong phạm vi. Tự hỏi điều gì có thể là lỗi.

lỗi mới:

make 
g++ -Wall main1.o -o main 
Undefined      first referenced 
symbol        in file 
arrayListType<int>::seqSearch(int const&) constmain1.o 
ld: fatal: Symbol referencing errors. No output written to main 
collect2: ld returned 1 exit status 
*** Error code 1 
make: Fatal error: Command failed for target `main1' 
+1

bản sao có thể có của [Tại sao tôi phải truy cập các thành viên cấp cơ sở mẫu thông qua con trỏ này?] (Http://stackoverflow.com/questions/4643074/why-do-i-have-to-access-template- base-class-members-through-the-this-pointer) – Pradhan

Trả lời

47

Điều này là do mẫu phụ huynh của lớp mẫu không được khởi tạo trong thời gian qua biên soạn mà lần đầu tiên xem xét các mẫu. Những tên này dường như không phụ thuộc vào việc khởi tạo mẫu cụ thể và do đó các định nghĩa cần phải có sẵn. (Nếu bạn không bao giờ nhìn vào định nghĩa của arrayListType, sau đó đọc mã của unorderedArrayListType nó sẽ xuất hiện các listlength cần phải có một số loại như là toàn thể.)

Bạn sẽ cần phải nói với trình biên dịch một cách rõ ràng rằng tên là trong thực tế phụ thuộc vào sự khởi tạo của phụ huynh.

Một cách, sử dụng this-> trước tất cả tên được kế thừa: this->list, this->length.

Cách khác, sử dụng các khai báo: using arrayListType<elemType>::length; v.v. (ví dụ: trong phần riêng tư của lớp dẫn xuất).


Một entry FAQ về vấn đề này: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

+0

Cảm ơn! Tôi đã sử dụng "using arrayListType :: length" và giải quyết các lỗi liên quan đến các biến không được khai báo trong phạm vi. Tôi chỉ còn một lỗi nữa mà tôi đã đăng vào cuối câu hỏi. Bạn có thể xin vui lòng bình luận về điều đó. Cảm ơn! – Romonov

+2

@ user640639: Thông báo lỗi cuối cùng có vẻ bị xáo trộn, nhưng những gì nó nói với bạn là bạn chưa định nghĩa một hàm thành viên mà bạn đã khai báo. Các hàm thành viên ảo phải được xác định xem chúng có được sử dụng trong mã của bạn hay không và bạn không cung cấp việc triển khai thực hiện một hàm cụ thể nào đó. –

+0

@Rodriguez Cảm ơn! Bạn đúng rồi. Đã xảy ra lỗi trong khai báo hàm ảo của tôi về seqSearch. Tôi đã sửa chữa nó và nó hoạt động ngay bây giờ. – Romonov

5

tôi sẽ cố gắng hai điều:

1. Sử dụng this-> (mà nói chung là một ý tưởng tốt để làm với các mẫu).

template <class elemType> 
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem) 
{ 
    for(int i = this->length; i > location; i--) 
     this->list[i] = this->list[i - 1]; 

    this->list[location] = insertItem; 
    this->length++; 
} 

2. typedef phụ huynh và sử dụng nó khi truy cập vào các thành viên mẹ:

template <class elemType> 
class unorderedArrayListType: public arrayListType<elemType> 
{ 
    typedef arrayListType<elemType> Parent; 
    ... 
} 

template <class elemType> 
void unorderedArrayListType<elemType>::insertAt(int location, const elemType& insertItem) 
{ 
    for(int i = Parent::length; i > location; i--) 
     Parent::list[i] = Parent::list[i - 1]; 

    Parent::list[location] = insertItem; 
    Parent::length++; 
} 
9

Một bình luận mở rộng về câu trả lời UncleBens'.

Bạn nên nhớ rằng các mẫu lớp không phải là các lớp. Chúng là các mẫu. Một cách để xem xét nó: Trong C++, các lớp không phải là các đối tượng. Bạn cần khởi tạo một lớp để tạo một đối tượng. Một khái niệm tương tự áp dụng cho các lớp và các lớp của lớp. Cũng giống như instantiation class tạo một đối tượng, class instantiation tạo ra một class.

Cho đến khi mẫu được khởi tạo, mối quan hệ thừa kế bạn thiết lập giữa unorderedArrayListTypearrayListType không hoàn toàn tồn tại. Trình biên dịch không biết nếu bạn định xác định một phần mẫu instantiation của arrayListType không có lengthlist làm thành viên dữ liệu. Bạn cần phải cung cấp cho trình biên dịch một tay trong unorderedArrayListType của bạn bằng cách sử dụng this->lengththis->list hoặc một số cấu trúc khác cho trình biên dịch biết rằng bạn mong đợi đây là thành viên dữ liệu.

Giả sử bạn sử dụng this->length trong unorderedArrayListType, và giả sử có ai đó xuất hiện và viết một mẫu instantiation một phần của arrayListType<FooType> mà không có lengthlist như các thành viên dữ liệu. Bây giờ instantiating một unorderedArrayListType<FooType> sẽ dẫn đến lỗi biên dịch thời gian. Nhưng kể từ khi bạn sẽ không làm điều đó (bạn sẽ không làm điều đó, là bạn?), Sử dụng this->length sẽ là OK.

+1

Bạn sẽ viết một "bản mẫu một phần của arrayListType mà không có độ dài và danh sách thành viên dữ liệu "? Bạn có thể thêm một ví dụ cho câu trả lời của bạn? Cảm ơn. –

Các vấn đề liên quan