2

所以,我有以下类和方法:

属性:有一个类型的成员int(命名mTag

TypedProperty:从Property类继承并添加一个名为mValuetype的成员T

PropertyList:一个维护 a std::setofProperty并具有AddandPrint方法的类。

CheckSubset:一种检查 astd::set是否包含在另一个集合中的方法。

我不知道我应该如何实现该CheckSubset方法。因为我不知道如何遍历一个set<Property>和访问模板成员(mValue)。我也尝试使用该includes方法,但它不起作用(即使它有效,我也不知道它是怎么做到的!)。方法中存在同样的问题PropertyList::Print,我不知道应该使用什么演员表。
任何有关实施CheckSubsetPrint方法的建议将不胜感激!

更新源代码(使用指针)

#include <string>
#include <iostream>
#include <set>
#include <algorithm>
#include <tr1/memory>

using namespace std;

/////////////////// Property Class //////////////////////

class Property
{
public:
    Property(){};
    Property(const int tag)
            : mTag(tag) {}
    virtual ~Property() {}
    int mTag;
    bool operator<(const Property &property) const
    {
        return mTag < property.mTag;
    }
};

/////////////////// TypedProperty Class /////////////////

template< typename T >
class TypedProperty : public Property
{
public:
    TypedProperty (const int tag, const T& value)
            : Property(tag), mValue(value){}
    T mValue;
};

/////////////////////////////////////////////////////////

typedef std::tr1::shared_ptr<Property> PropertyPtr;

/////////////////// PropertyList Class /////////////////

class PropertyList
{
public:
    PropertyList(){};
    virtual ~PropertyList(){};
    template <class T>
    void Add(int tag, T value) 
    {
    PropertyPtr ptr(new TypedProperty<T>(tag, value));
        mProperties.insert(ptr);
    }
    void Print()
    {
    for(set<PropertyPtr>::iterator itr = mProperties.begin(); itr != mProperties.end(); itr++)
    {
        cout << ((PropertyPtr)*itr)->mTag << endl; 
        // What should I do to print mValue? I do not know its type
        // what should *itr be cast to? 
    }
    }
    set<PropertyPtr> mProperties;
};

//////////////////// Check Subset ///////////////////////
/*
 * Checks if subset is included in superset 
 */
bool CheckSubset(set<PropertyPtr> &superset, set<PropertyPtr> &subset)
{
    // How can I iterate over superset and subset values while I do not know
    // the type of mValue inside each Property?
    // I also tried the following method which does not seem to work correctly
    return includes(superset.begin(), superset.end(), 
            subset.begin(), subset.end());
}

int main()
{
    PropertyList properties1;
    properties1.Add(1, "hello");
    properties1.Add(2, 12);
    properties1.Add(3, 34);
    properties1.Add(4, "bye");

    properties1.Print();

    PropertyList properties2;
    properties2.Add(1, "hello");
    properties2.Add(3, 34);


    if(CheckSubset(properties1.mProperties, properties2.mProperties)) // should be true
        cout << "properties2 is subset!" << endl;

    PropertyList properties3;
    properties3.Add(1, "hello");
    properties3.Add(4, 1234);

    if(CheckSubset(properties1.mProperties, properties3.mProperties)) // should be false
        cout << "properties3 is subset!" << endl;
}
4

2 回答 2

5

你想要的,不能用当前的设计来完成。

你的方法失败了std::set<Property>

std::set<Property>会切片。这意味着它只会复制Property部分而忘记复制其他TypedProperty<T>成员。

结果,在内部PropertyList::print(),没有办法访问 mValue。

如果要将TypedProperty<T>s 存储在 astd::set中,则必须使用某种指针。即要么std::set<Property*>,要么智能指针版本。

于 2012-10-29T12:34:46.130 回答
1

为了解决Print方法中的问题PropertyList,您可以为类编写一个Print方法TypedProperty,该方法打印其标签和值。

但是关于访问mValue您想要对其进行一些操作的问题,我想不出一种使用普通类型和模板来获得的方法,mValue而无需让您的父类Property使用模板类型TypedProperty(这似乎是不可取的)。但是您可以获取地址mValue并将其转换为void*以消除类型问题。这样您将面临另一个问题,即您不能指向void*指针的值,因此您不能在父级使用指针。因此,您应该编写一个方法(由 实现TypedProperty),该方法接受一个void*指针并将其强制转换为 child 中定义的类型并执行所需的操作。

例如,在下面的代码中,我假设您想检查 a 中的值TypedProperty与另一个相同类型(IsEqual方法)的值是否相等。

现在您可以简单地实现CheckSubset使用IsEqual(检查两个元素就像:)superItr->IsEqual(subItr->GetValue())

class Property
{
    public:
        Property(){};
        Property(const int tag)
            : mTag(tag) {}
        virtual ~Property() {}
        virtual void* GetValue() = 0;
        virtual bool IsEqual(void* value) = 0;
        virtual void Print() = 0;
        int mTag;
        bool operator<(const Property &property) const
        {
            return mTag < property.mTag;
        }
};


template< typename T >
class TypedProperty : public Property
{
    public:
        TypedProperty (const int tag, const T& value)
            : Property(tag), mValue(value){}
        void* GetValue()
        {
            return &mValue;
        }
        bool IsEqual(void* value)
        {
            return *((T*)value) == mValue;
        }
        void Print()
        {
            cout << "Tag: " <<  mTag << ", Value: " << mValue << endl;
        }
        T mValue;
};

typedef std::tr1::shared_ptr<Property> PropertyPtr;

class PropertyList
{
    public:
        PropertyList(){};
        virtual ~PropertyList(){};
        template <class T>
            void Add(int tag, T value) 
            {
                PropertyPtr ptr(new TypedProperty<T>(tag, value));
                mProperties.insert(ptr);
            }
        void Print()
        {
            cout << "-----------" << endl;
            for(set<PropertyPtr>::iterator itr = mProperties.begin(); itr != mProperties.end(); itr++)
            {
                (*itr)->Print();
            }
        }
        set<PropertyPtr> mProperties;
};
于 2012-10-29T13:56:14.677 回答