多态性并检查对象是否具有某种成员方法

时间:2010-08-16 19:25:39

标签: c++ pointers polymorphism

我正在和朋友一起开发一个GUI库,我们遇到了如何确定某个元素是否应该可点击的问题(或者是可移动的,等等)。

我们决定只检查特定对象是否存在函数,所有gui元素都存储在带有指向基类的指针的向量中。

例如,如果我有

class Base {};
class Derived : public Base
{
    void example() {}
}
vector<Base*> objects;

如何检查对象成员是否具有名为example的函数。

如果这不可能实现可选行为(例如点击等)的不同方式。

5 个答案:

答案 0 :(得分:8)

您可以在基类中使用虚拟IsClickable()方法:

class Widget {
public:
    virtual bool IsClickable(void) { return false; }
};
class ClickableWidget : public Widget
{
public:
    virtual bool IsClickable(void) { return true; }
}
class SometimesClickableWidget : public Widget
{
public:
    virtual bool IsClickable(void); 
    // More complex logic punted to .cc file.
}
vector<Base*> objects;

这样,对象默认不可点击。可点击对象可以覆盖IsClickable()或子类ClickableWidget而不是Widget。不需要花哨的元编程。

编辑:确定某些内容是否可点击:

if(object->IsClickable()) {
   // Hey, it's clickable!
}

答案 1 :(得分:4)

最好的方法是使用mixin多重继承,a.k.a。接口。

class HasExample // note no superclass here!
{
    virtual void example() = 0;
};

class Derived : public Base, public HasExample
{
    void example()
    {
        printf("example!\n");
    }
}

vector<Base*> objects;
objects.push_back(new Derived());

Base* p = objects[0];
HasExample* he = dynamic_cast<HasExample*>(p);
if (he)
    he->example();

dynamic_class&lt;&gt;()在运行时测试给定对象是否实现HasExample,并返回HasExample *或NULL。但是,如果您发现自己使用的是HasExample *,那么通常需要重新考虑您的设计。

小心!当像这样使用多重继承时,那么(HasExample *)ptr!= ptr。将指针强制转换为其父项之一可能会导致指针的值发生变化。这是完全正常的,在方法内部,这将是您所期望的,但如果您不了解它,它可能会导致问题。

编辑:添加了dynamic_cast&lt;&gt;()的示例,因为语法很奇怪。

答案 2 :(得分:1)

我会创建一个接口,使方法成为接口的一部分,然后在任何应该具有该功能的类上实现该接口。

在尝试确定Object是否实现某些功能集(而不是检查方法名称)时,这将是最有意义的:

class IMoveable
{
    public:
        virtual ~IMoveable() {}
        virtual void Move() = 0;
};

class Base {};

class Derived : public Base, public IMoveable
{
    public:
        virtual void Move()
        {
            // Implementation
        }
}

现在您不再检查方法名称,而是转换为IMoveable类型并调用Move()。

答案 3 :(得分:1)

如果您愿意使用RTTI。 。

您应该创建ClickableMovable等类,而不是检查类名。然后,您可以使用dynamic_cast查看各种元素是否实现了您感兴趣的界面。

IBM有一个简短的示例程序,用于说明dynamic_cast here

答案 4 :(得分:0)

我不确定通过反思做到这一点很容易或很好。我认为更好的方法是拥有一个具有GUIElement功能的接口(类似于isClickable)。使您的元素实现接口,然后可点击的元素将在函数的实现中返回true。所有其他人当然会回归虚假。当您想知道某些内容是否可点击时,只需将其命名为isClickable即可。这样,您可以在运行时将元素从可点击变为不可点击 - 如果在您的上下文中有意义的话。