2009-08-28 39 views
7

Tôi muốn biết kiểm tra kiểu tĩnh và động là gì và sự khác biệt giữa chúng.Kiểm tra kiểu tĩnh và động trong C++

+2

c'mon ... Thứ ba trên google: http://www.sitepoint.com/article/typing-versus-dynamic-typing/ ... điều rep-scheme này thực sự tài trợ yêu cầu tất cả các loại câu hỏi. ..> thở dài < – jpinto3912

+7

Mục tiêu của stackoverflow là trở thành kho lưu trữ của tất cả các kiến ​​thức lập trình, ngay cả khi nó tồn tại ở một nơi khác. –

+7

Tôi biết nó ở đâu đó trên google, nhưng ở đây bạn nhận được nhiều định nghĩa giúp bạn hiểu rõ hơn một cách rõ ràng hơn – rkb

Trả lời

15

Kiểm tra loại tĩnh nghĩa là việc kiểm tra loại xảy ra tại thời gian biên dịch. Không có thông tin kiểu nào được sử dụng trong thời gian chạy trong trường hợp đó.

Kiểm tra loại động xảy ra khi thông tin loại được sử dụng khi chạy. C++ sử dụng một cơ chế gọi là RTTI (thông tin kiểu thời gian chạy) để thực hiện điều này. Ví dụ phổ biến nhất mà RTTI được sử dụng là các nhà điều hành dynamic_cast cho phép downcasting các loại đa hình:

// assuming that Circle derives from Shape... 
Shape *shape = new Circle(50); 
Circle *circle = dynamic_cast<Circle*> shape; 

Bên cạnh đó, bạn có thể sử dụng toán tử typeid để tìm hiểu về các loại thời gian chạy của các đối tượng. Ví dụ, bạn có thể sử dụng nó để kiểm tra xem hình dạng trong ví dụ là hình tròn hay hình chữ nhật. Dưới đây là một số further information.

+3

Cần lưu ý rằng static_cast hoàn toàn hợp lệ trong ví dụ trên, đơn giản. dynamic_cast chỉ nên được sử dụng nếu bạn không chắc chắn rằng hình dạng là loại Circle, trong trường hợp dynamic_cast sẽ trả về NULL (hoặc ném một ngoại lệ nếu bạn đang đúc một tham chiếu). –

0

Kiểm tra loại tĩnh là kiểm tra loại được thực hiện tại thời gian biên dịch. Đây là kiểu kiểm tra duy nhất mà C++ thực hiện. Kiểm tra kiểu động là loại kiểm tra được thực hiện tại thời gian chạy. Điều này thường được nhìn thấy trong các ngôn ngữ thông dịch động, nhưng ít phổ biến hơn trong các ngôn ngữ được biên dịch. Cuối cùng tôi đã kiểm tra, C++ không thực hiện bất kỳ loại kiểm tra động nào.

Chỉnh sửa: Dường như tôi đã lỗi thời. Xem nhận xét của Reed dưới đây.

+8

dynamic_cast tồn tại trong C++ và chạy kiểm tra kiểu thời gian trên nhiều thời gian chạy C++. –

+0

Tôi đã sửa chữa :) Cảm ơn! –

2

Có nhiều loại phôi có sẵn trong C++.

Phổ biến nhất là sử dụng static_cast để truyền biến từ một loại con trỏ này sang loại khác. Tuy nhiên, bạn cũng có thể sử dụng dynamic_cast, thao tác này sẽ kiểm tra để đảm bảo (tại thời điểm chạy) mà con trỏ có loại chính xác. Với dynamic_cast, nếu con trỏ không phải là kiểu đúng, khi chạy, nó sẽ trả về 0 để thay thế.

// Assume these classes exist 
// class A 
// class B 
// class C : B 

C* c = new C(); 
A* a = new A(); 

B* b = static_cast<B*>(a); // this will work! 
b = dynamic_cast<B*>(a); // b == NULL 
b = dynamic_cast<B*>(c); // b is valid 
+0

"B * b = static_cast (a); // điều này sẽ hoạt động!": Bạn không nên bình luận điều này là "điều này sẽ biên dịch và bạn nhận được con trỏ không NULL; Nhưng nó sẽ không nhất thiết phải hoạt động!"? – mmmmmmmm

+0

Tôi nghĩ rằng thực sự static_cast chỉ hoạt động cho các loại liên quan và sẽ từ chối biên dịch, reinterpret_cast sẽ là cần thiết trong trường hợp này. Những ví dụ đó trông có vẻ rối tung với tôi. –

3

C++ có rất ít hỗ trợ cho loại động kiểm tra một là thông qua dynamic_cast và khác là thông qua type id .Both thể được sử dụng chỉ khi hỗ trợ RTTI được kích hoạt trong trình biên dịch.

TYPE& dynamic_cast<TYPE&> (object); 
TYPE* dynamic_cast<TYPE*> (object); 

Từ khóa dynamic_cast lấy biểu đồ từ một con trỏ hoặc loại tham chiếu khác, thực hiện kiểm tra thời gian chạy để đảm bảo tính hợp lệ của dàn diễn viên.

Nếu bạn cố gắng truyền tới con trỏ tới loại không phải là loại đối tượng thực, kết quả của phép tính sẽ là NULL. Nếu bạn cố gắng truyền để tham chiếu đến một loại không phải là một loại đối tượng thực tế, diễn viên sẽ ném một ngoại lệ bad_cast.

Đảm bảo có ít nhất một chức năng ảo trong lớp cơ sở để thực hiện công việc dynamicast.

// expre_typeid_Operator.cpp 
// compile with: /GR /EHsc 
#include <iostream> 
#include <typeinfo.h> 

class Base { 
public: 
    virtual void vvfunc() {} 
}; 

class Derived : public Base {}; 

using namespace std; 
int main() { 
    Derived* pd = new Derived; 
    Base* pb = pd; 
    cout << typeid(pb).name() << endl; //prints "class Base *" 
    cout << typeid(*pb).name() << endl; //prints "class Derived" 
    cout << typeid(pd).name() << endl; //prints "class Derived *" 
    cout << typeid(*pd).name() << endl; //prints "class Derived" 
    delete pd; 
} 
2

Giả sử bạn có:

class A {}; 
class B:A {}; 

A* a = new B(); 
B* b = new B(); 

Đối với loại tĩnh, bạn nhìn vào cách các biến được khai báo.

A* a = ... 
B* b = ... 

Vì vậy, các loại tĩnh của aA* (hay nói cách khác, loại tĩnh của *aA).

Và loại tĩnh của bB* (hoặc để đặt theo cách khác, loại tĩnh của *bB).

Lưu ý rằng ab có loại tĩnh được cố định bởi tuyên bố của nó - không quan trọng bạn đặt gì vào chúng, chúng sẽ giữ cùng loại tĩnh. ("tĩnh" có nghĩa là "không thay đổi").


Đối với loại động, bạn nhìn vào những gì sẽ xảy ra trong biến ngay bây giờ.

a = new B(); 
b = new B(); 

Vì vậy, các loại năng động của ab đều B* (hay nói cách khác, các loại năng động của *a*b đều B).

Lưu ý rằng loại động có thể thay đổi - nếu bạn đã làm a = new A() thì loại động của a vừa được đổi thành A*. Đôi khi bạn không biết loại động là gì - ví dụ: nếu bạn làm a = somefunc() thì a có thể có loại động A*, B* hoặc thậm chí C* (nếu một số mã bạn chưa thấy định nghĩa C làm lớp con của A hoặc B).

Nếu A có phương thức virtual trên đó, thì bạn có thể sử dụng dynamic_cast để tìm ra loại động nào. (Thông thường, nếu bạn đang sử dụng loại mã này, bạn muốn có thể thực hiện delete a; để làm việc đó là A 's destructor phải là virtual. Và làm cho virtual destructor A đủ để dynamic_cast hoạt động).

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