2010-10-15 21 views
10

Giả sử tôi có mã nàyC++ là destructor ảo vẫn cần thiết nếu không có thành viên dữ liệu trong nguồn gốc?

class Base{ 
    public: 
     int getVal(); 
    private: 
     int a, b; 
}; 

class Derived::public Base{ 
    public: 
     void printVal(); 
}; 

int main(){ 
    Base *b = new Derived(); 
    delete b;  
} 

Tôi biết một destructor ảo sẽ xóa mọi thứ đúng cách, nhưng là nó xấu để xóa với con trỏ cơ sở (khi không có destructor ảo) ngay cả khi không có chức năng ảo và không có các thành viên dữ liệu trong lớp dẫn xuất? Điều gì sẽ xảy ra nếu điều này được thực hiện?

Trả lời

5

Đối với dữ liệu kiểu nguyên thủy, ví dụ của bạn rất có thể sẽ hoạt động trong thực tế. Như một vấn đề của thực tế, phát sinh một vtable có thể thực sự cản trở hiệu suất (vì vậy có thể có một số sử dụng hợp pháp ở đây), nhưng nó về mặt kỹ thuật không xác định, mỗi 5,3-5,4:

Nếu loại tĩnh của toán hạng [của toán tử xóa] khác với loại độngđộng của nó, loại tĩnh phải là lớp cơ sở của loại hoạt động loại động và loại tĩnh có hành vi hủy ảo hoặc hành vi không xác định.

Thực sự tất cả phụ thuộc vào "mức độ" của dữ liệu trong lớp của bạn và vì không có thành viên được phân bổ (trong trường hợp của bạn), bạn nên ổn, nhưng chắc chắn là mã.

+2

Cảm ơn David. – snk

+3

Thật nguy hiểm khi dựa vào những thứ sẽ "có khả năng hoạt động" và cho rằng bạn "nên ổn thôi". Tốt hơn là viết mã mà _will_ làm việc, sau đó bạn _know_ bạn sẽ ổn thôi. –

+0

James, tôi sẽ đảm bảo rằng luôn luôn có một destructor ảo. Đây chỉ là một giả thuyết được hỏi bởi một ai đó và không có câu trả lời cho nó. Cảm ơn cả hai một lần nữa. – snk

9

Bạn có thể xóa bằng con trỏ cơ sở (khi không có trình phá hủy ảo) ngay cả khi không có chức năng ảo và không có thành viên dữ liệu trong lớp dẫn xuất?

Có.

Hành vi không xác định bất kể nội dung của lớp dẫn xuất.

Điều gì sẽ xảy ra nếu việc này được thực hiện?

Mọi thứ đều có thể xảy ra.

+1

Cảm ơn bạn rất nhiều James. – snk

+3

+1 cho "Mọi thứ đều có thể xảy ra". Bất cứ điều gì! Tuyệt đối bất cứ điều gì! :) – ybungalobill

2

Bộ dẫn hướng ảo trong lớp dẫn xuất là cần thiết để gọi đúng hàm hủy có nguồn gốc (đa hình), khi đối tượng dẫn xuất được tạo ra thông qua một con trỏ đến lớp cơ sở.

Quy tắc CPP toàn vẹn cao 3.3.2 Viết trình phá hủy 'ảo' cho các lớp cơ sở. (QACPP 2116)

biện minh: Nếu một đối tượng sẽ bị phá hủy thông qua một con trỏ đến lớp cơ sở, thì lớp cơ sở đó sẽ có trình phá hủy ảo. Nếu destructor lớp cơ sở không phải là ảo, chỉ có destructor cho lớp cơ sở sẽ được gọi. Trong hầu hết các trường hợp, các destructor phải là ảo, bởi vì việc bảo trì hoặc tái sử dụng có thể thêm các lớp dẫn xuất đòi hỏi một destructor ảo.

class Base {}; 
class Derived : public Base { public: ~Derived() {} }; 

void foo() { 
    Derived* d = new Derived; delete d; // correctly calls derived destructor 
} 
void boo() { 
    Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor! 
} 
+0

Tôi nghĩ rằng bạn có nghĩa là destructor của bạn được đặt tên là '~ Derived', không phải' ~ C' ... –

+0

@ Mike Ellery, có đó là những gì tôi muốn có nghĩa là. Tôi đã sửa mã. – ArBR

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