2010-01-14 33 views
12

Nó phải là một cái gì đó cụ thể trong mã của tôi, mà tôi không thể đăng. Nhưng có lẽ ai đó có thể gợi ý nguyên nhân có thể xảy ra.Phương pháp C++ chỉ hiển thị khi đối tượng truyền tới lớp cơ sở?

Về cơ bản tôi có:

class CParent 
{ 
public: 
    void doIt(int x); 
}; 
class CChild : public CParent 
{ 
public: 
    void doIt(int x,int y,int z); 
}; 

CChild *pChild = ... 
pChild->doIt(123); //FAILS compiler, no method found 
CParent *pParent = pChild; 
pParent->doIt(123); //works fine 

Làm thế nào trên trái đất?

CHỈNH SỬA: mọi người đang nói về bóng/ẩn. Nhưng hai phiên bản của doIt có số lượng tham số khác nhau. Chắc chắn rằng không thể nhầm lẫn trình biên dịch, quá tải trong lớp con mà không thể nhầm lẫn với phiên bản lớp cha? Có thể không?

Các lỗi biên dịch tôi nhận được là: lỗi C2660: 'CChild :: DoIT': chức năng không mất 1 lập luận

+0

Wow. Điều này là không nhiều để đi về ... –

+1

Tôi ngạc nhiên khi bạn nhìn thấy bất kỳ phương pháp nào cả. –

+0

về cơ bản tôi có ... về không có gì? –

Trả lời

29

Bạn đã shadowed một phương pháp. Ví dụ:

struct base 
{ 
    void method(int); 
    void method(float); 
}; 

struct derived : base 
{ 
    void method(int); 
    // base::method(int) is not visible. 
    // base::method(float) is not visible. 
}; 

Bạn có thể khắc phục điều này với một chỉ thị using:

class derived : public base 
{ 
    using base::method; // bring all of them in. 

    void method(int); 
    // base::method(int) is not visible. 
    // base::method(float) is visible. 
}; 

Vì bạn dường như van lơn về số lượng các thông số, tôi sẽ giải quyết vấn đề đó. Điều đó không thay đổi bất cứ điều gì. Quan sát:

struct base 
{ 
    void method(int){} 
}; 

struct derived : base 
{ 
    void method(int,int){} 
    // method(int) is not visible. 
}; 

struct derived_fixed : base 
{ 
    using base::method; 
    void method(int,int){} 
}; 

int main(void) 
{ 
    { 
     derived d; 

     d.method(1, 2); // will compile 
     d.method(3); // will NOT compile 
    } 
    { 
     derived_fixed d; 

     d.method(1, 2); // will compile 
     d.method(3); // will compile 
    } 
} 

Nó sẽ vẫn được shadowed không phụ thuộc tham số hoặc trở lại các loại; nó chỉ đơn giản là các tên là tên mà bóng. using base::<x>; sẽ hiển thị tất cả các phương thức "<x>" của .

+0

Tuyệt vời, tôi không nghĩ rằng tôi vẫn sẽ khám phá ra những tính năng kỳ lạ và bất ngờ của C++. –

+2

Chỉ thị sử dụng sẽ không đưa tất cả các phương thức của lớp cơ sở vào tầm nhìn. Vâng, trong trường hợp này có, nhưng nói chung. Nó sẽ mang tất cả các phương thức với tên được đề cập trong chỉ thị sử dụng vào tầm nhìn. Đó là nit-picky của tôi, vâng. Nhưng đó là một sự khác biệt quan trọng. – Omnifarious

+0

Đúng, hãy để tôi giải quyết điều đó. – GManNickG

0

Vấn đề là CChild không thực sự kế thừa từ CParent.

Và vì vậy, nó không có phương thức doIt chỉ lấy một đối số.

+0

typo. cố định. = ngay bây giờ. –

-2

Phương pháp trong lớp con của bạn có số lượng đối số khác với những gì bạn đang cố gắng vượt qua. Nó có thể liên quan đến điều đó không?

2

Bạn đang gặp sự cố cổ điển. Bạn cần using CParent::doIt; trong lớp CChild của mình. Tôi sẽ xem xét các câu hỏi trùng lặp.

Edit:

Dưới đây là câu trả lời của tôi để về cơ bản cùng một câu hỏi: Overriding a Base's Overloaded Function in C++

+0

Cái gì? Quá tải trong lớp con có các tham số khác nhau đối với lớp cha. Tại sao nó lại là một vấn đề? –

+0

Đọc câu trả lời được liên kết. Tôi nghĩ nó sẽ giải thích mọi thứ. –

+0

Tất cả các ví dụ được đăng đều là quá tải với cùng số lượng đối số. Tôi có thể thấy những người sẽ nhầm lẫn trình biên dịch. Nhưng khi nó nhìn thấy doit (123), và tìm thấy doIt (x, y, z), tại sao nó sẽ coi đây là một trận đấu và ngừng tìm kiếm? –

1

Tôi chưa bao giờ làm điều này mà không có phương pháp đó trong lớp cơ sở trước đây. Tôi nghĩ rằng việc thêm "sử dụng CLASS :: METHOD" trong lớp dẫn xuất sẽ cho phép bạn truy cập vào phiên bản khác của phương thức quá tải.

class CParent 
{ 
public: 
    void doIt(int x); 
}; 
class CChild : public CParent 
{ 
public: 
    void doIt(int x,int y,int z); 

    using CParent::doIt; 
}; 
0

Khi bạn ghi đè hàm trong lớp dẫn xuất, chỉ có thể hiển thị đối tượng người dùng của lớp đó. Phiên bản lớp cơ sở sẽ bị ẩn.

Vì vậy, con trỏ pChild của bạn gọi doIt (int x) sẽ thất bại vì bạn đang sử dụng một con trỏ lớp dẫn xuất để gọi hàm lớp cơ sở. Con trỏ pParent gọi doIt (int x) sẽ hoạt động vì bạn đang sử dụng một con trỏ lớp cơ sở để gọi hàm lớp cơ sở. Mặc dù bạn có một đối tượng con được trỏ đến bởi một con trỏ cha mẹ (upcasted), kiểu lớp ở đây được xác định bởi khai báo của con trỏ là một CParent.

Để có thể gọi đó là chức năng lớp cơ sở bằng cách sử dụng con trỏ lớp được thừa kế, bạn có thể:

  1. Đủ điều kiện tên lớp cơ sở trong các cuộc gọi chức năng, như trong những điều sau đây:

    pChild->CParent::doIt(123);

  2. Sử dụng chỉ thị sử dụng để đưa tên hàm từ lớp cơ sở vào lớp dẫn xuất, như đã thấy trong các bài viết trước.

0

Tôi hiểu rằng hành vi này là để bạn linh hoạt ghi đè hành vi của phương thức lớp cơ sở trong lớp dẫn xuất của bạn.

Giả sử bạn có hàm foo (int) trong lớp cơ sở và bạn muốn thay đổi hành vi của hàm này trong lớp dẫn xuất của bạn. Bây giờ nếu phương thức lớp cơ sở không bị ẩn bởi phương thức lớp dẫn xuất của bạn (có cùng nguyên mẫu giống như phương thức của lớp cơ sở), nó sẽ giới thiệu sự mơ hồ về độ phân giải quá tải.

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