2013-04-17 32 views
7

Với các lớp C++, bạn có thể có một lớp dẫn xuất kế thừa một biến từ lớp cha của nó. Làm thế nào tôi có thể xác định lớp dẫn xuất để var2 không được kế thừa trong derivclass?Làm thế nào để không kế thừa một biến trong các lớp C++

class mainclass{ 
public: 
    int var1; 
    char var2; 
    void test(){ 
     cout<<var1<<var2<<endl; 
    } 
} 
class derivclass : mainclass{ 
public: 
    void test(){ 
     cout<<var1<<var2<<endl; 
     //want a compiler error here that var2 is not defined 
    } 
} 
+3

Make nó 'private'. Bạn không thể tránh thừa kế nếu thành viên là 'công khai'. –

+4

nếu bạn định nghĩa nó là 'private' trong' mainclass', thì 'derivclass' sẽ không thể chạm vào nó, nhưng nó vẫn sẽ * tồn tại * – Dave

+0

từ khóa riêng tư sẽ làm. –

Trả lời

7

Cách kinh điển để ngăn thành viên được kế thừa trong C++ là khai báo số private. Các lớp có nguồn gốc cố gắng truy cập nó sau đó sẽ ném một lỗi trình biên dịch. Nó sẽ giống như sau:

class mainclass{ 
public: 
    int var1; 
    void test(){ 
     cout<<var1<<var2<<endl; 
    } 
private: 
    char var2; 
} 
class derivclass : mainclass { 
    public: 
    void test(){ 
     cout<<var1<<var2<<endl; 
     //compiler error here; var2 is not accessible 
    } 
} 

Đây là cách đơn giản nhất để đạt được những gì bạn đang yêu cầu.

+2

Tôi nghĩ rằng bạn đã 'var1' và' var2' đảo ngược trong ví dụ của bạn. 'var1' sẽ không thể truy cập được trong ví dụ của bạn. –

+0

Ah OK, cảm ơn. Điểm là tôi muốn tạo biến không kế thừa có sẵn từ bên ngoài 'lớp chính'. Nếu tôi định nghĩa một getter và setter là 'inline', điều đó sẽ tạo ra overhead? – tomsmeding

+0

@tomsmeding: Vì vậy, bạn muốn biến có thể truy cập từ bên ngoài 'lớp chính' cho tất cả mọi người * ngoại trừ *' derivclass'? Tôi không nghĩ điều đó có thể xảy ra; nếu một thành viên là công khai, hoặc có một công khai, thì mọi người có thể truy cập nó, bao gồm cả các lớp dẫn xuất. Hoặc nó sẽ đáp ứng nhu cầu của bạn nếu lớp dẫn xuất có thể truy cập biến nhưng chỉ thông qua một getter? – Edward

4

Bạn có thể làm cho nó private. Nhưng bạn có lẽ không nên.

Thực tế là nó không nên kế thừa một số công cụ từ cơ sở có nghĩa là nó có lẽ không nên kế thừa từ cơ sở trực tiếp ở tất cả.

Thay vào đó tạo một lớp cơ sở khác và làm cho hai lớp kế thừa từ cơ sở đó.

class Baseclass{ 
public: 
    void test(){ 
     cout<<var1<<endl; 
    } 
protected: 
    int var1; 

} 

class mainclass : public Baseclass{ 
public: 
    char var2; 
    void test(){ 
     cout<<var1<<var2<<endl; 
    } 
} 

class derivclass : Baseclass{ 
public: 
    void test(){ 
     cout<<var1<<endl; 
    } 
} 
+0

Nếu bạn bỏ phiếu, xin vui lòng có lịch sự để ít nhất là lý do tại sao. – stardust

+0

Tôi sẽ cung cấp cho bạn một điểm trở lại vì câu trả lời của bạn là tốt. Không biết tại sao ai đó lại bỏ phiếu này. –

+1

Tôi không bỏ phiếu cho câu trả lời của bạn, nhưng điều tốt nhất cần làm là luôn làm cho các thành viên dữ liệu của bạn riêng tư, và xác định getters và setters khi cần thiết. Xem "Hiệu quả C++" của Scott Meyers. – Dima

2

Như mọi người nói, bạn có thể đặt riêng tư trong lớp cơ sở và không thể truy cập ở bất kỳ lớp con nào. Tuy nhiên, như @Dave nói, nó vẫn sẽ tồn tại bên trong lớp cơ sở. Nếu bạn thậm chí không muốn nó tồn tại như một biến được ẩn khỏi các lớp con, thì bạn phải lấy nó ra khỏi lớp cơ sở. Giả sử rằng biến là cần thiết cho một cái gì đó, sau đó bạn phải tạo một lớp con mới chứa biến đó.

0

Lớp dẫn xuất kế thừa mọi thành viên của các cơ sở của nó. Ngừng hẳn. Bạn không thể kế thừa có chọn lọc các phần của một lớp cơ sở.

Đặt biến riêng tư không ngăn chặn việc thừa kế. Biến vẫn còn đó, nhưng trong những hoàn cảnh bình thường thì nó không thể truy cập được. Với các trò chơi tình bạn khác nhau, bạn có thể làm cho nó dễ tiếp cận. Có thể một phần của sự nhầm lẫn ở đây là do Java, nơi mà các thành viên riêng không được kế thừa. Đó là,

struct Base { 
private: 
    int i; 
}; 

struct Derived : Base { 
}; 

Derived d; 
d.i = 3; // error: d.i is not accessible 

Nếu i đã không được thừa kế, sai số sẽ là d không có thành viên mang tên i.

EDIT: một, có lẽ ý nghĩa hơn, ví dụ

void f(); 

class Base { 
    void f(); 
}; 

class Derived : Base { 
    void g() { 
     f(); // error: Base::f is not accessible 
}; 

Với quy tắc của Java, các cuộc gọi đến f() sẽ ổn, và sẽ gọi toàn cầu f().

+0

@KonradRudolph - Uh, không có gì. Thế còn bạn? –

+0

Bạn cũng không chắc chắn cách bạn nhận được ý tưởng rằng Java có thể loại bỏ thành viên một cách kỳ diệu khi kế thừa. Tất nhiên trong Java một lớp dẫn xuất thừa kế * tất cả * thành viên cơ sở của nó. –

+0

@KonradRudolph - Tôi không nói rằng nó có thể loại bỏ thành viên một cách kỳ diệu khi kế thừa. –

0

Để trả lời tất cả các câu trả lời khác (và có thể chuyển đổi từ Stochastically), bạn có thể chuyển lớp chính và lớp dẫn xuất, trong đó lớp chính mới sẽ có tất cả các giá trị thành viên mà bạn muốn trong lớp dẫn xuất ban đầu, những cái không cần thiết trong lớp có nguồn gốc mới (hay còn gọi là lớp chính gốc)

Quan sát:

class newMainClass{ 
public: 
    int var1; 
    virtual void test(){ //added virtual here so there aren't two definitions for test() 
     cout<<var1<<var2<<endl; 
     //want a compiler error here that var2 is not defined 
    } 
} 

class newDerivedClass : public newMainClass{ 
public: 
    char var2; 
    void test(){ 
     cout<<var1<<var2<<endl; 
    } 
} 
+0

Tôi thích tư duy "ra khỏi hộp", nhưng đây không thực sự là một giải pháp. Thay vào đó, nó là một cách để tránh vấn đề. Đảo ngược quan hệ thừa kế không phải lúc nào cũng có thể. – Julian

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