2010-03-12 45 views
24
class Base 
{ 
    public: 
    int base_int; 
}; 

class Derived : public Base 
{ 
    public: 
    int derived_int; 
}; 

Base* basepointer = new Derived(); 
basepointer-> //Access derived_int here, is it possible? If so, then how? 
+3

Bạn có thực sự muốn sử dụng kế thừa riêng không? –

+1

Ai đó thêm một người kết thúc câu lệnh vào nó. Tôi chỉ thay đổi một ký tự. –

Trả lời

38

Không, bạn không thể truy cập derived_intderived_int là một phần của Derived, trong khi basepointer là một con trỏ đến Base.

Bạn có thể làm điều đó theo chiều ngược lại mặc dù:

Derived* derivedpointer = new Derived; 
derivedpointer->base_int; // You can access this just fine 

lớp Derived kế thừa các thành viên của lớp cơ sở, không phải là cách khác xung quanh.

Tuy nhiên, nếu basepointer của bạn đã được trỏ đến một thể hiện của Derived sau đó bạn có thể truy cập nó thông qua một dàn diễn viên:

Base* basepointer = new Derived; 
static_cast<Derived*>(basepointer)->derived_int; // Can now access, because we have a derived pointer 

Lưu ý rằng bạn sẽ cần phải thay đổi kế thừa của bạn để public đầu tiên:

class Derived : public Base 
+1

không nên sử dụng dynamic_cast thay vì static_cast? –

+9

Điều đó tùy thuộc vào việc anh ta có biết rằng đó là một 'Có nguồn gốc' hay không. Nếu bạn chắc chắn 100% (như chúng ta đang ở đây) thì 'static_cast' là tốt. –

+0

không phải ai cũng có nghĩa là reinterpret_cast thay vì static_cast? Tôi khá chắc chắn static_cast sẽ không biên dịch. – Balk

9

Bạn đang nhảy múa trên bãi mìn ở đây. Các lớp cơ sở không bao giờ có thể biết rằng nó thực sự là một thể hiện của nguồn gốc. Cách an toàn nhất để làm điều đó sẽ được giới thiệu một hàm ảo trong cơ sở:

class Base 
{ 
protected: 
virtual int &GetInt() 
{ 
    //Die horribly 
} 

public: 
int base_int; 
}; 

class Derived : Base 
{ 
    int &GetInt() 
    { 
    return derived_int; 
    } 
public: 
int derived_int 
}; 

basepointer->GetInt() = 0; 

Nếu điểm basepointer như một cái gì đó khác mà một nguồn gốc, chương trình của bạn sẽ chết khủng khiếp, đó là kết quả mong muốn.

Hoặc, bạn có thể sử dụng dynamic_cast (basepointer). Nhưng bạn cần ít nhất một hàm ảo trong Base cho nó, và được chuẩn bị để gặp một số không.

static_cast <>, như một số gợi ý, là cách chắc chắn để tự chụp chân mình. Đừng đóng góp vào bộ nhớ cache khổng lồ về "câu chuyện kinh dị của gia đình ngôn ngữ C".

+0

"Ngoài ra, bạn có thể sử dụng dynamic_cast (basepointer). Nhưng bạn cần ít nhất một hàm ảo trong Base cho điều đó, và được chuẩn bị để gặp phải một số không." -> Good Point Seva.Liked It :) – mahesh

+3

Sử dụng 'static_cast' không phải là cách để tự bắn mình vào chân. Tôi nghĩ rằng bạn đang bối rối với ký hiệu cast rõ ràng của C '(T) x'. 'static_cast' mặt khác là loại an toàn, nhưng' dynamic_cast' sẽ trả về một con trỏ null nếu nó không thể chuyển đổi trong khi 'static_cast' sẽ phát hành một lỗi trình biên dịch. – 0x499602D2

4

bạn có thể sử dụng CRTP

về cơ bản bạn sử dụng các lớp có nguồn gốc trong các mẫu cho các lớp cơ sở

3

Có thể bằng cách cho phép các lớp cơ sở biết loại lớp dẫn xuất. Điều này có thể được thực hiện bằng cách làm cho lớp cơ sở là một mẫu của kiểu dẫn xuất. Thành ngữ C++ này được gọi là curiously recurring template pattern.

Hiểu biết về lớp dẫn xuất, con trỏ lớp cơ sở có thể được đúc tĩnh thành con trỏ đến kiểu dẫn xuất.

template<typename DerivedT> 
class Base 
{ 
public: 
    int accessDerivedField() 
    { 
     auto derived = static_cast<DerivedT*>(this); 
     return derived->field; 
    } 
}; 


class Derived : public Base<Derived> 
{ 
public: 
    int field; 
}; 

int main() 
{ 
    auto obj = new Derived; 
    obj->accessDerivedField(); 
} 
0

// nếu bạn biết những gì có nguồn gốc lớp học mà bạn sẽ sử dụng

Derived * derivedpointer = dynamic_cast < Derived *> basepointer;

// thì bạn có thể truy cập lớp dẫn xuất bằng cách sử dụng derivedpointer

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