Trong Java, bạn có thể tạo một Ánh xạ ánh xạ các kiểu đối tượng String tới Generic có thể được đúc một cách rõ ràng đến các lớp khác. Có cách nào tốt đẹp để bắt chước chức năng này trong C++?C++ Tương đương với Bản đồ Java <String, Object>
Trả lời
Là ngôn ngữ được nhập khá mạnh, C++ không có "Loại đối tượng chung". Nó chắc chắn có các thùng chứa liên kết: std::map
(một hương vị của cây nhị phân) và std::unordered_map
(một hương vị của bảng băm). Điều nào tốt hơn tùy thuộc vào trường hợp sử dụng và thường không thể được quyết định mà không có hồ sơ.
Điều gần nhất với đối tượng chung mà tôi có thể nghĩ là một tổ tiên chung cho tất cả các đối tượng có thể được đặt trong bản đồ này. Ở đây, ý tưởng là tạo ra một hệ thống phân cấp lớp với đa hình động và lưu trữ các đối tượng trong bản đồ dưới dạng con trỏ được đúc vào tổ tiên chung đó. Thiết kế lý tưởng sẽ làm cho việc đúc các vật thể này trở về lớp dẫn xuất của chúng không cần thiết. Nếu thay vào đó, bạn cần phải sử dụng dynamic_cast
(và có thể kiểm tra xem nó có thành công hay không).
Bắt buộc phải lưu con trỏ vào các đối tượng trên bản đồ, chứ không phải chính đối tượng. Nếu không, đối tượng cố gắng chèn vào bản đồ, chỉ có phần tổ tiên chung sẽ được lưu trữ và tính đa hình sẽ bị mất. Nó cũng cần phải được quyết định xem bản đồ sở hữu các đối tượng hay không (không có bộ sưu tập rác ở đây). Nếu không, con trỏ đơn giản có thể hoạt động. Nếu bản đồ sở hữu các đối tượng, tôi khuyên bạn nên lưu trữ chúng trong "con trỏ duy nhất" (std::unique_ptr
). Wrapping lên:
#include <unordered_map>
#include <string>
#include <memory> // std::unique_ptr<>, std::make_unique()
#include <iostream>
class NotSoGenericClass {
public:
virtual ~NotSoGenericClass() = default;
virtual std::string name() const
{ return "NotTooGenericClass()"; }
};
class EvenLessGenericClass: public NotSoGenericClass {
int fValue = 0;
public:
EvenLessGenericClass(int value): fValue(value) {}
virtual std::string name() const override
{ return "EvenLessGenericClass(" + std::to_string(fValue) + ")"; }
int value() const { return fValue; }
};
int main() {
//
// map holding (and owning) "not so generic objects"
//
std::unordered_map<std::string, std::unique_ptr<NotSoGenericClass>> allObjects;
//
// populate it
//
allObjects["any"] = std::make_unique<NotSoGenericClass>();
allObjects["six"] = std::make_unique<EvenLessGenericClass>(6);
allObjects["one"] = std::make_unique<EvenLessGenericClass>(1);
std::cout << "Object 'six' says: " << allObjects["six"]->name() << std::endl;
std::cout << "Now dumping all " << allObjects.size() << " objects:";
for (auto const& keyAndObject: allObjects) {
auto const& key = keyAndObject.first;
auto const* object = keyAndObject.second.get();
//
// base class interface is always available:
//
std::cout << "\n[" << key << "] " << object->name();
//
// object-specific one requires a cast:
//
auto const* lessGen = dynamic_cast<EvenLessGenericClass const*>(object);
if (lessGen) std::cout << " (value is " << lessGen->value() << ")";
} // for
std::cout << std::endl;
return 0;
} // main()
Trên nền tảng của tôi, mã này (sử dụng C++ 14) phát ra:
[one] EvenLessGenericClass(1) (value is 1)
[six] EvenLessGenericClass(6) (value is 6)
[any] NotTooGenericClass()
(cũng minh họa ý nghĩa của "thứ tự" trong tên bản đồ). Ví dụ này được biên dịch với g++ -Wall -pedantic -std=c++14 -o test.exe test.cpp
(GCC 6.4.0).
Trong C++ 17, bạn có thể sử dụng std :: map < std :: string, std :: any >.
- 1. Bản đồ Java tương đương trong C#
- 2. Có một bản đồ Java keySet() tương đương với bản đồ std :: của C++ không?
- 3. C# tương đương với Java tiếp tục <label>?
- 4. Tương đương với C++ map.lower_bound trong Java
- 5. Java tương đương với bản đồ chức năng trong Python
- 6. C# tương đương với chức năng bản đồ trong Haskell
- 7. C# Uri.EscapeDatastring() tương đương với Java
- 8. Cách chuyển bản đồ <String, String> với application.properties
- 9. Java Generics đặt trên Bản đồ <String,? mở rộng Danh sách <String>>
- 10. Tương đương với "Danh sách <String>" của C# trong PHP là gì?
- 11. Java tương đương với OpenLayers
- 12. C# tương đương với tài nguyên Java
- 13. C# tương đương với charAt của Java()?
- 14. java tương đương với C# ExpandoObject
- 15. C# tương đương với Java dụ initializer
- 16. C++ tương đương với Java này
- 17. C# tương đương với Iterator trong Java
- 18. Tương đương với C# ObservableCollection trong Java
- 19. Tại sao java.util.Properties thực hiện Bản đồ <Object, Object> và không phải Bản đồ <String, String>
- 20. Java Annotation C# tương đương
- 21. .NET tương đương với Java wildcard (IInterf <?>)?
- 22. Mảng Java & Generics: Java Tương đương với C# IEnumerable <T>
- 23. Double.doubleToLongBits tương đương với C#?
- 24. Scala tương đương với Java java.lang.Class <T> Object
- 25. Bản đồ JPA <String, String> mapping
- 26. C# Regex tương đương với Java appendReplacement và appendTail
- 27. Java Tương đương với Reflection.Emit
- 28. C tương đương với ++ STL C
- 29. java tương đương với mkstemp
- 30. Tại sao Bản đồ không <String, Đặt <String>> khớp với Bản đồ <T, Set<?>>?
Có bản đồ trong C++ 11/14, std :: map. xin vui lòng kiểm tra xem nó có thể đáp ứng yêu cầu của bạn. – tibetty
và cũng ['std :: unordered_map'] (http://en.cppreference.com/w/cpp/container/unordered_map) –
tôi nghĩ rằng op đang nói về một đối tượng lớp có thể chấp nhận bất kỳ loại đối tượng nào ... không phải về bộ sưu tập vùng chứa dữ liệu Bản đồ –