2009-09-03 42 views
5

Hey, Trong C++, tôi có một vector loại:Vector vòng lặp Đúc

vector<BaseClass*> myVector; 

Trong đó, tôi chèn (push_back) gợi ý của các lớp thừa vào nó.

Bây giờ, tôi muốn bật lại phần tử của nó vì vậy tôi làm điều này:

vector<ADlgcDev*>::iterator iter; 

for (iter = myVector.rbegin(); iter != myVector.rend(); iter++) 
{ 
// but before I pop it, I need to shutdown it down 
// so I cast this 
// but this way, I'm unable to call the function 
(DerivedClass*(*iter))->Shutdown(); 

myVector.pop_back(); 
} 

nhưng khi đề cập đến trong các ý kiến ​​trước khi tôi bật nó, tôi cần phải gọi Shutdown() phương pháp của nó và các diễn viên cũng không hoạt động bình thường. Bất kỳ độ phân giải nào? hoặc là không thể?

+3

BTW, vòng lặp của bạn bị hỏng - hoặc bỏ vòng lặp 'for' của bạn và xóa' myVector.pop_back() ', hoặc bỏ nó vào và thay đổi thành vòng lặp' while' để kiểm tra phần tử 'back()' mỗi lần như sbi cho thấy. –

+0

Vòng lặp của tôi bị hỏng như thế nào? – akif

+1

Nếu bạn tinh thần thực hiện các bước với một mảng gồm 10 mục, bạn sẽ thấy rằng bạn chỉ xử lý ngày 5 đầu tiên, bởi vì vào lúc đó bạn đã xóa 5 số cuối cùng bằng 'pop_back()'. –

Trả lời

13
while (!myVector.empty()) 
{ 
    ((DerivedClass*)(myVector.back()))->Shutdown(); 
    myVector.pop_back(); 
} 

Ghi chú:

  • Bạn có lẽ nên sử dụng dynamic_cast thay vì các diễn viên cứng. (Nếu chắc chắn rằng chỉ có DerivedClass đối tượng trong véc tơ, tại sao không phải là std::vector<DerivedClass>?)
  • Có thể bạn không cần phải đúc gì cả, vì Shutdown() phải được khai báo trong lớp cơ sở.
  • Có lẽ bạn cũng nên xóa các đối tượng trước khi bật chúng ra khỏi vectơ. (Nhưng điều đó có thể không phải như vậy.)
  • Có lẽ bạn nên sử dụng con trỏ thông minh gọi Shutdown() (và delete, có thể).

Edit: Sử dụng std::vector<T>::clear(), as shown by markh44 có lẽ là tốt hơn so với pop_back().

+0

Lời khuyên tuyệt vời, đặc biệt là bullet # 2. Nhưng stefaanv là đúng, phôi theo kiểu hàm dựng sẽ không hoạt động đối với các kiểu con trỏ - thay vào đó, hãy làm như anh ta gợi ý. –

+0

Tôi đồng ý với các bình luận và tôi thích vòng lặp mới – stefaanv

+0

Thậm chí tốt hơn - loại bỏ 'Shutdown()' và đặt chức năng trong destructor (mà phải trở thành 'virtual' vì bạn sẽ xóa một lớp dẫn xuất qua một con trỏ lớp cơ sở). Sử dụng một 'vector >' thay vào đó, và sau đó bạn sẽ không cần phải nhớ để làm * bất cứ điều gì! * –

1

Việc tạo hàm tạo không hoạt động đối với con trỏ. Sử dụng static_cast nếu bạn chắc chắn hoặc dynamic_cast và kiểm tra.

-1

Nếu tắt máy() là một phương pháp ảo của lớp cơ sở tức là BaseClass :: Shutdown() bạn nên gọi trực tiếp iter-> ShutDown();

Nếu không, nếu phương pháp không phải là ảo, bạn nên sử dụng dynamic_cast.

vector<ADlgcDev*>::iterator iter; 

for (iter = myVector.rbegin(); iter != myVector.end(); iter++) 
{ 
DerivedClassA* a = dynamic_cast<DerivedClassA*>(*iter) ; 
if (a) a->ShutDownA(); 
else 
{ 
DerivedClassB* b = dynamic_cast<DerivedClassB*>(*iter); 
if (b) b->ShutDownB(); 
// ... repeat for every class in hierarchy that might be in the vector. 
} 
myVector.pop_back(); 
} 

Dù sao có lẽ bạn đang bị rò rỉ bộ nhớ, trừ khi ShutDown() xóa các đối tượng từ bản thân (mà nói chung là một ý tưởng tồi) hoặc bạn đang giữ con trỏ trùng lặp và xóa chúng ở những nơi khác, đó là một ý tưởng nguy hiểm.

+0

Bạn đã xem những gì 'lặp' là được khởi tạo với và nó được so sánh với cái gì? Và bạn sẽ chọn cái nào để 'myVector.pop_back()' không làm mất hiệu lực với trình lặp? Và nếu có các lớp dẫn xuất _several_ có hàm 'ShutDownX()', thì hàm _very_ có thể là một hàm ảo được khai báo trong lớp cơ sở. – sbi

+0

Tôi vừa tạo ra những thay đổi tối thiểu cho thiết kế của mình. Tất nhiên nó nên được bắt nguồn, và toàn bộ vòng lặp có thể được viết thành hai dòng. – davidnr

2

Bạn có thể tắt chức năng ảo trong BaseClass không? Sau đó, bạn sẽ không cần một diễn viên.

Cũng có thể bạn sẽ gặp sự cố khi xóa các mục khỏi vectơ trong khi lặp lại. Tôi sẽ làm như sau:

vector<BaseClass*>::iterator iter; 

for (iter = myVector.rbegin(); iter != myVector.rend(); iter++) 
{ 
    (*iter)->Shutdown(); 
} 
myVector.clear(); 

Chỉnh sửa: và một điều khác, + + thường được ưu tiên hơn lặp lại ++.

+0

Tôi đoán 'rbegin()' so với 'end()' cũng có thể gây rắc rối. Mặc dù sử dụng 'clear()' là một ý tưởng rất hay. – sbi

+0

@sbi meh, làm thế nào mà có được trong đó? Tôi chắc chắn rằng tôi đã sao chép và dán mã đó ... – markh44

+0

@ markh44: Đó là vấn đề. Đó là một trong những vấn đề với mã gốc. – sbi

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