2013-06-20 17 views
5

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!

Trả lời

2

Tương tự như giải pháp của bạn nhưng không bị mất hiệu lực *.

class NodeVisitor 
{ 
    virtual void VisitBlack(BlackNode* node); 
    virtual void VisitWhite(BlackNode* node); 
}; 

class BaseNode { 
    std::vector<BaseNode*> children_; 
    ... 
    virtual void visit(NodeVisitor* visitor) = 0; 
}; 

class WhiteNode : public BaseNode { 
    virtual void visit(NodeVisitor* visitor) { visitor->visitWhite(this); } 
}; 

class BlackNode : public BaseNode { 
    virtual void visit(NodeVisitor* visitor) { visitor->visitBlack(this); } 
}; 

Sau đó

std::string convert(BaseNode* node) 
{ 
    class ConvertVisitor 
     : public NodeVisitor 
    { 
     ConvertVisitor(std::string* res) 
      : m_res(res) 
     { } 

     virtual void VisitBlack(BlackNode* node) 
     { 
      *m_res = // convert black node to string; 
     } 

     virtual void VisitWhite(BlackNode* node) 
     { 
      *m_res = // convert white node to string; 
     } 

     std::string* m_res; 
    }; 

    std::string res; 
    ConvertVisitor visitor(&res); 
    node->visit(&visitor); 
    return res; 
} 
+0

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

+0

Điều đó sẽ không hoàn toàn khả thi. Bạn có hỗ trợ C++ 11 không? –

+0

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

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