2010-09-26 45 views
16

tôi là lập trình viên mới trong C++. và tôi đang sử dụng các mẫu cho lần đầu tiên.thừa kế mẫu C++

tôi có lớp trừu tượng và một lớp khác mở rộng nó. nhưng tất cả các thành viên protected của lớp trừu tượng không được công nhận bởi các lớp khác:

class0.h:

template<class T> 
class class0 { 

protected: 
    char p; 
public: 
    char getChar(); 
}; 

**class1.h** 
template<class T> 
class class1:public class0<T> { 
public: 
    void printChar(); 
}; 
template<class T> 
void class1<T>::printChar(){ 
    cout<< p<<endl;//p was not declared in this scope 
} 

cảm ơn bạn. có một tuần tuyệt vời =)

+0

Các lớp cơ sở của bạn cần có trình phá hủy ảo công khai hoặc một trình phá hủy không ảo/được bảo vệ. – GManNickG

+0

BTW, lớp nào trừu tượng trong điều này? – Chubsdad

Trả lời

26

Lý do khiến điều này xảy ra là phải làm theo quy tắc tìm kiếm mẫu.

p không phải là biểu thức phụ thuộc vì nó chỉ là số nhận dạng chứ không phải là thông tin phụ thuộc vào thông số mẫu. Điều này có nghĩa là các lớp cơ sở phụ thuộc vào tham số mẫu sẽ không được tìm kiếm để giải quyết tên p. Để giải quyết vấn đề này, bạn cần phải sử dụng một cái gì đó phụ thuộc vào tham số mẫu. Sử dụng this-> sẽ thực hiện việc này.

ví dụ:

cout << this->p << endl; 
+0

Cảm ơn bạn! đã giúp =) có một ngày tốt lành! – yonka

+3

@yonka: Bạn nên chấp nhận câu trả lời của mình. – GManNickG

+0

@GMan: Tôi không biết; litb đã đăng câu trả lời ngay bây giờ. :-) –

2

Tôi không gặp lỗi trình biên dịch đó trong VC9. Tuy nhiên, có một số vấn đề với mã: Đầu tiên, nó không cần phải là một lớp mẫu như nó hiện đang được viết ... nhưng có lẽ bạn chỉ đơn giản hóa nó cho câu hỏi này? Thứ hai, lớp cơ sở nên có một destructor ảo.

#include <iostream> 

using namespace std; 

class class0 { 
public: 
    virtual ~class0(){} 

protected: 
    char p; 
public: 
    char getChar(); 
}; 

class class1 : public class0 { 
public: 
    void printChar(); 
}; 

void class1::printChar(){ 
    cout << p << endl;//p was not declared in this scope 
} 

int main() { 
    class1 c; 
    c.printChar(); 
    return 1; 
} 

Vì bạn đang tìm hiểu về các mẫu, tôi sẽ đề nghị không trộn các khái niệm (thừa kế & mẫu) trong khi học tập. Bắt đầu với một ví dụ đơn giản như thế này ...

#include <iostream> 
#include <string> 

using namespace std; 

template <typename T> 
T add(const T& a, const T& b) { 
    return a + b; 
} 

int main() { 
    int x = 5; 
    int y = 5; 

    int z = add(x, y); 
    cout << z << endl; 

    string s1("Hello, "); 
    string s2("World!"); 

    string s3 = add(s1, s2); 
    cout << s3 << endl; 

    return 1; 
} 

Các khái niệm quan trọng trong đoạn code trên là chúng ta đã viết ONE chức năng mà biết làm thế nào để thêm các số nguyên và chuỗi (và nhiều loại khác cho rằng vấn đề).

+4

Tại sao lớp cơ sở có một destructor ảo? Các mẫu thường được sử dụng để thực hiện đa hình tham số và xóa ảo chỉ hữu ích cho đa hình động (và chỉ khi xóa được thực hiện đa hình). –

+1

Trình biên dịch Visual Studio 2008 được biết là không thực hiện đúng các quy tắc tra cứu mẫu trong trường hợp này. Đây là lý do tại sao bạn không thấy lỗi. –

+0

@Ben Voigt, điểm tốt nhưng OP chỉ mới bắt đầu với các mẫu và tôi đã đoán rằng họ có thể chưa bao hàm điều đó. Nhưng nó trông giống như họ đã bao gồm thừa kế và trừ khi anh ta đặc biệt đi cho đa hình thời gian biên dịch nó an toàn nhất để làm cho cơ sở destructor ảo. – dgnorton

14

Đối với một tên được ngẩng đầu lên trong một lớp cơ sở phụ thuộc, hai điều kiện cần phải được thỏa mãn

  • Đó là cần thiết rằng tra cứu là không đủ tiêu chuẩn
  • Đó là cần thiết rằng tên là phụ thuộc

Các quy tắc này được nêu trong C++ 03 khác với rules stated by unrevised C++98, nơi đáp ứng dấu đầu dòng thứ hai (tạo tên phụ thuộc) là đủ để tìm tên được khai báo trong các lớp cơ sở phụ thuộc.

Tên phụ thuộc được tra cứu tại thời điểm khởi tạo và tra cứu khác với tra cứu không đủ tiêu chuẩn sẽ không bỏ qua các lớp cơ sở phụ thuộc. Cả hai điều kiện này cần phải được thỏa mãn để tìm một tên được khai báo trong một lớp cơ sở phụ thuộc, không chỉ một mình trong số đó là đủ.Để đáp ứng cả hai điều kiện bạn có thể sử dụng các cấu trúc khác nhau

this->p 
class1::p 

Cả hai tên p phụ thuộc và phiên bản đầu tiên sử dụng truy cập tra cứu thành viên lớp và phiên bản thứ hai sử dụng tên đủ điều kiện tra cứu.