Tôi có dữ liệu được lưu trữ trong cấu trúc cây C++ mà tôi đọc từ một tệp. Cây trông giống như sau:Kết hợp các mẫu và kế thừa trong chuyển đổi cây
class BaseNode {
std::vector<BaseNode*> children_;
...
};
class WhiteNode : public BaseNode { ... };
class BlackNode : public BaseNode { ... };
Sau khi cây được xây dựng, tôi muốn chuyển đổi nó, ví dụ: vào một chuỗi.
Để giữ mã cây tách biệt với mã chuyển đổi, tôi muốn sử dụng các mẫu, tức là thực hiện một cái gì đó như thế:
template <class T>
T WhiteNode::Convert() { ... };
Tuy nhiên, vì các nút cây được lưu trữ như BaseNode*
, tôi don không biết cách truy cập chức năng thành viên mẫu như vậy. Và kể từ khi các chức năng thành viên mẫu không thể được kế thừa, tôi không nghĩ rằng điều này sẽ làm việc.
tôi đã tìm ra một giải pháp làm việc, mặc dù:
class BaseConversion {
public:
virtual ~BaseConversion() {}
virtual void * FromBlack() = 0;
virtual void * FromWhite() = 0;
};
template <class T>
class Conversion : public BaseConversion {
public:
void * FromBlack();
void * FromWhite();
};
class BaseNode {
std::vector<BaseNode*> children_;
virtual void * Convert(BaseConversion * conversion) = 0;
public:
virtual ~BaseNode() {}
template <class T>
T Convert() {
return *static_cast<T*>(Convert(new Conversion<T>));
}
};
class WhiteNode : public BaseNode {
void * Convert(BaseConversion * conversion) {
return conversion->FromWhite();
}
};
class BlackNode : public BaseNode {
void * Convert(BaseConversion * conversion) {
return conversion->FromBlack();
}
};
Và logic chuyển đổi có thể được hoàn toàn riêng biệt:
template <>
void * Conversion<std::string>::FromWhite() {
return new std::string("converting WHITE node to std::string ...");
}
template <>
void * Conversion<std::string>::FromBlack() {
return new std::string("converting BLACK node to std::string ...");
}
kiểm tra mã:
BaseNode * node = new BlackNode;
std::cout << node->Convert<std::string>() << std::endl;
node = new WhiteNode;
std::cout << node->Convert<std::string>() << std::endl;
lợi nhuận kết quả mong đợi:
converting BLACK node to std::string ...
converting WHITE node to std::string ...
Mặc dù giải pháp này hoạt động, tôi chắc chắn rằng nó có thể được thực hiện dễ dàng hơn nhiều. Bất kỳ giải pháp đơn giản nào khác, tôi đã đưa ra không thành công, ví dụ: do loại tẩy xoá.
Tôi sẽ đánh giá cao bất kỳ trợ giúp nào về điều đó. Cảm ơn!
Cảm ơn. Tránh con trỏ void có thể thanh lịch hơn một chút. Tuy nhiên, tôi đang tìm kiếm một cái gì đó nhỏ gọn hơn, có thể không có các lớp chuyển đổi hoặc khách truy cập. – DonDieselkopf
Điều đó sẽ không hoàn toàn khả thi. Bạn có hỗ trợ C++ 11 không? –
Có, tôi có. Nếu có một giải pháp C++ 11, tôi sẽ tò mò. Tôi đã thực sự mong đợi một số giải pháp như CRTP. Nhưng nhìn vào ứng dụng của tôi, tôi trở nên ngày càng bị cám dỗ để gắn bó với mô hình khách truy cập. Tuy nhiên, bất kỳ ý kiến khác rất hoan nghênh. – DonDieselkopf