C ++:强制定义静态成员

时间:2014-04-25 11:13:46

标签: c++

我有 Components 的不同集合,其中每个Component都是抽象类 IComponent 的子类。 IComponent 定义了一个纯虚函数{{1}因此,每个组件都需要为它创建一个实现。

考虑每个组件只能添加一次,因此其ID等于所有实例和集合函数

virtual ID_TYPE getId() = 0;

我希望有一个额外的静态方法,就像上面描述的那样,以便检索组件的ID而无需按顺序创建实例(可能没有默认构造函数)像

这样的东西
IComponent* ICollection::getComponent(const ID_TYPE);

我知道虚拟静态成员之类的东西并不存在,并且无法覆盖静态方法。但是可以有任何其他方法来确保collection1.getComponent(MyComponentA::getId())->something(); collection2.getComponent(MyComponentA::getId())->something(); 的每个子类定义这样的静态方法吗?

3 个答案:

答案 0 :(得分:1)

所以我会选择这样的东西:

ComponentBase.h:

template <typename T>
class ComponentBase {
   ....
   .... 
protected:
   ComponentBase() { (void)getClassId(); }
public:
   static int getClassId();
   ....
};

Component1.h:

#include "ComponentBase.h"

class Component1: public ComponentBase<Component1> {
public:
    Component1(....) {}
    ....
};

Component1.cc:

#include "Component1.h"

....

template <>
int ComponentBase<Component1>::getClassId() {
    return 1;
}

如果开发人员忘记为类ComponentBase<ComponentX>::getClass()定义ComponentX,则该项目将不会链接。

实际上我不会将ID的选择留给组件开发人员。这种技术允许提供仅基于ComponentX类名称的通用实现,从而“免费”获得ID的唯一性。

答案 1 :(得分:0)

一种方法是制作一些模板魔法,以防你可以修改IComponent接口和类。类似的东西:

#include <iostream>

using namespace std;
typedef int ID_TYPE;

class IComponent
{
public:
    IComponent() {}

    template <class T>
    ID_TYPE gclassId()
    {
        return T::classId(); 

    }

    virtual ID_TYPE getId() = 0;
};

class Comp1 : public IComponent
{
public:
    Comp1() {}
    virtual ID_TYPE getId() {return IComponent::gclassId<Comp1>();}
    static ID_TYPE classId() {return 1; }
};

class Comp2 : public IComponent
{
public:
    Comp2() {}
    virtual ID_TYPE getId() {return IComponent::gclassId<Comp2>(); }
    static ID_TYPE classId() {return 2;}
};

    /*
class Comp3 : public IComponent
{
public:
    Comp3() {}
    virtual ID_TYPE getId() {return IComponent::gclassId<Comp3>(); }
};
    */

int main()
{
    Comp1 a;
    Comp2 b;
    IComponent* t = new Comp2();
    std::cout << a.getId() << t->getId();
    delete t;
    return 0;
}

这要求每个IComponent派生类声明一个静态成员classId()。如果取消注释Comp3,则会出现编译错误。

通过修改它我的意思是你可以访问源代码。请忽略您的ID_TYPE的typedef,它可以是您想要的任何内容,只要您的虚拟函数通过gclassIdIComponent返回真实ID,而{{1}}依次变为强制性来自班级的静态方法。

答案 2 :(得分:0)

我不知道有什么方法可以强制派生类实现一个成员,除非通过纯虚方法。

我建议只使用纯虚拟或类似的文档来指示ID应该是类实现的唯一,而不是类实例。在理想的世界中,您应该能够依靠派生类的开发人员来阅读方法的文档,以了解它需要返回静态标识符而不是实例标识符。无论如何,你必须依靠它们来正确实现其他纯虚方法。