C++:如何将子类数据存入基类vector并以子类类型遍历
Absolutely feasible! This is a classic use case for C++ polymorphism with smart pointers. Let's break down how to move your AccountsStruct data into the inherited Data vector, plus how to safely iterate over it later as AccountsStruct instances:
1. Populate the Data vector from your loaded vector<AccountsStruct>
Since AccountsStruct publicly inherits from DataStruct, a std::unique_ptr<AccountsStruct> can be implicitly converted to std::unique_ptr<DataStruct>. You can transfer ownership of each AccountsStruct object into the Data vector using either a loop or std::transform for conciseness:
// Assume you have your loaded data stored here: std::vector<AccountsStruct> loadedAccounts; // Option 1: Range-based for loop for (auto& account : loadedAccounts) { // Use std::move to avoid copying the entire struct Data.push_back(std::make_unique<AccountsStruct>(std::move(account))); } // Option 2: More concise with std::transform std::transform( loadedAccounts.begin(), loadedAccounts.end(), std::back_inserter(Data), [](AccountsStruct&& acc) { return std::make_unique<AccountsStruct>(std::move(acc)); } );
Important: Make sure
DataStructhas a virtual destructor! Without it, theunique_ptrwon't call the correct destructor forAccountsStructwhen cleaning up, leading to memory leaks and undefined behavior. Define it like this:struct DataStruct { virtual ~DataStruct() = default; // Critical for safe polymorphism // Add other virtual methods if needed for your use case };
2. Iterate over Data as AccountsStruct instances
To access the AccountsStruct-specific members, you'll need to safely downcast the DataStruct pointers. The safest way to do this is with dynamic_cast, which performs a runtime type check to ensure the conversion is valid:
for (const auto& dataPtr : Data) { // Attempt to cast the base pointer to AccountsStruct* if (auto* account = dynamic_cast<AccountsStruct*>(dataPtr.get())) { // Now you can access all AccountsStruct members safely std::cout << "Account ID: " << account->id << ", Username: " << account->username << "\n"; } else { // Handle unexpected data types (though this shouldn't happen if LoadTable is properly implemented) std::cerr << "Warning: Found non-AccountsStruct data in Accounts table!\n"; } }
If you're 100% certain that every element in Data is an AccountsStruct (since it's populated by the Accounts class's LoadTable method), you could use static_cast for slightly better performance. However, dynamic_cast is always safer—it prevents undefined behavior if someone accidentally adds a different DataStruct subclass to the vector later.
Bonus: Add type-safe helper methods (optional)
To make iteration cleaner, you could add a helper method to the Accounts class that returns a view of the Data vector as AccountsStruct pointers:
class Accounts : public MySQLTable { public: // ... existing LoadTable implementation ... std::vector<AccountsStruct*> GetAccounts() { std::vector<AccountsStruct*> result; for (const auto& ptr : Data) { auto* acc = dynamic_cast<AccountsStruct*>(ptr.get()); if (acc) result.push_back(acc); } return result; } };
Then you can iterate more simply:
Accounts accountsTable; accountsTable.LoadTable(); for (auto* account : accountsTable.GetAccounts()) { // Use account directly as AccountsStruct* }
内容的提问来源于stack exchange,提问作者Venelin

