2010-06-16 39 views
18

Tôi đã được hỏi câu hỏi điên rồ này. Tôi đã hết trí thông minh.Câu hỏi phỏng vấn về các chức năng ảo trong C++

Phương pháp trong lớp cơ sở được khai báo là ảo được gọi là sử dụng con trỏ lớp cơ sở trỏ đến đối tượng lớp dẫn xuất?

Điều này có khả thi không?

+9

Bạn có thể muốn có được một trong những cuốn sách giới thiệu từ [Sách hướng dẫn và sách định nghĩa C++ Definitive] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). –

+2

@ James: Tôi nghĩ anh ta hỏi xem bạn có thể gọi 'base :: foo()' not 'derived :: foo()' bằng cách sử dụng 'p' nếu' p' là 'base *' và trỏ tới một 'bắt nguồn ' –

+0

@John: Vậy? James là đúng, tuy nhiên. – sbi

Trả lời

49

Nếu bạn đang cố gắng gọi một phương thức ảo từ con trỏ lớp cơ sở, có.

Đó là tính đa hình.

Nếu bạn đang yêu cầu, với một con trỏ lớp cơ sở đến một lớp dẫn xuất, bạn có thể gọi một phương thức lớp cơ sở được overriden bởi lớp dẫn xuất không? Có đó cũng có thể bằng cách xác định phạm vi rõ ràng tên lớp cơ sở:

basePtr->BaseClass::myMethod();

+4

Đa hình là nơi nó lớp phương thức lớp dẫn xuất vì phương thức này là ảo trong lớp cơ sở. Trên thực tế gọi phương thức lớp cơ sở thông qua một con trỏ đến cơ sở ngay cả khi phương thức lớp cơ sở đã bị ghi đè là bỏ qua đa hình khác nhau. –

+1

Thực ra nó ngược lại. Câu hỏi đặt ra là yêu cầu gọi phương thức ảo của lớp cơ sở khi đối tượng là kiểu bắt nguồn ghi đè phương thức. – JaredPar

+5

Hrm, câu hỏi được viết là khó hiểu. – Alan

10

Bạn có nghĩa là một cái gì đó như thế này. (Nơi pBase là loại con trỏ-to-base nhưng nhọn để phản đối thực sự là loại Derived mà có nguồn gốc từ Base.)

pBase->Base::method(); 

Có, đó là có thể.

16

Hãy thử:

class A   { virtual void foo(); } 
class B : public A { virtual void foo(); } 

A *b = new B(); 
b->A::foo(); 
+4

Thực ra tôi nghĩ rằng nó nên là "A * b = new B()", thay vì "B * b = new B()", để theo dõi câu hỏi. – Luca

+1

Vâng, nó nên. –

-1

Không phải trong một cách sạch sẽ. Nhưng có. Bạn phải làm một số thao tác con trỏ, có được một con trỏ đến vtable và thực hiện cuộc gọi. nhưng đó không phải là chính xác một con trỏ đến lớp cơ sở, nhưng một số thao tác con trỏ thông minh. Một cách tiếp cận khác là sử dụng toán tử phân giải phạm vi trên lớp cơ sở.

+0

C++ hỗ trợ trực tiếp những gì câu hỏi yêu cầu. 'base-> base :: function()' sẽ thực hiện thủ thuật. Không cần phải hack vtable ở đây. –

+2

Đọc lại bài đăng của bạn. "nhà điều hành giải pháp phạm vi" không phải là "một cách tiếp cận khác". Đó là cách tiếp cận duy nhất bạn nên cân nhắc. –

+0

Tôi đồng ý. Phạm vi độ phân giải là cách .. –

10

Có - bạn phải ghi rõ tên đầy đủ mặc dù:

#include <iostream> 

struct base { 
    virtual void print() { std::cout << "Base"; } 
}; 

struct derived : base { 
    virtual void print() { std::cout << "Derived"; } 
}; 

int main() { 
    base *b = new derived; 
    b->base::print(); 
    delete b; 
    return 0; 
} 
5

Nếu tôi hiểu câu hỏi một cách chính xác, bạn có

class B 
{ 
public: 
    virtual void foo(); 
}; 

class D: public B 
{ 
public: 
    virtual void foo(); 
} 

B* b = new D; 

Và câu hỏi là, bạn có thể gọi B::foo().Câu trả lời là có, sử dụng

b->B::foo() 
0
class B 
{ 
public: 
    virtual void foo(); 
}; 

class D: public B 
{ 
public: 
    virtual void foo(); 
} 

B* b = new D; 

Thử gọi

(*b).foo() 

để gọi chức năng lớp cơ sở foo

+0

bạn có chắc chắn rằng điều này sẽ gọi hàm cơ sở lớp foo? bạn đã thử nghiệm chưa? – Vijay

+0

Đó là giả định chung của tôi rằng (* b) cuối cùng sẽ có đối tượng thích hợp nhưng trên biên dịch và chạy tôi thấy rằng đây không phải là trường hợp. Nó vẫn gọi hàm xuất phát. Điều này đã tạo ra sự nhầm lẫn đối với tôi cũng là sự khác biệt giữa (* b) .foo() và B b1 = * b; b1.foo() – Pardeep

0
class B { 
    public: virtual void foo(); 
}; 

class D: public B { 
    public: virtual void foo() 
    { 
     B::foo(); 
    }; 
} 

B* b = new D; 

Giải pháp:

  1. b->foo();
  2. b->B::foo()

  3. HOẶC không ghi đè/xác định foo() trong lớp D có nguồn gốc và gọi b-> foo()

  4. B objb = *b; objb.foo() ; // this is object slicing and not (*b).foo() as in one of the previous answers

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