在C ++中实现子类中的静态方法重载

时间:2009-06-05 19:56:21

标签: c++ class templates oop static

我有这样的事情:

class Base
{
  public:
    static int Lolz()
    {
      return 0;
    }
};

class Child : public Base
{
  public:
    int nothing;
};

template <typename T>
int Produce()
{
  return T::Lolz();
}

Produce<Base>();
Produce<Child>();

都返回0,这当然是正确的,但不需要。有没有在第二个类中强制执行Lolz()方法的显式声明,或者在使用Produce<Child>()时可能会抛出编译时错误?

或者OO设计是否糟糕,我应该做一些完全不同的事情?

修改

我基本上想要做的是做出像这样的工作:

Manager manager;

manager.RegisterProducer(&Woot::Produce, "Woot");
manager.RegisterProducer(&Goop::Produce, "Goop");

Object obj = manager.Produce("Woot");

或更一般地说,外部抽象工厂不知道它正在生成的对象类型,因此可以添加新类型而无需编写更多代码。

5 个答案:

答案 0 :(得分:7)

有两种方法可以避免它。实际上,这取决于你想说什么。

(1)将Produce()作为Base类的接口。

template <typename T>
int Produce()
{
  return T::Lolz();
}
class Base
{
    friend int Produce<Base>();

protected:
    static int Lolz()
    {
        return 0;
    }
};

class Child : public Base
{
public:
    int nothing;
};

int main(void)
{
    Produce<Base>(); // Ok.
    Produce<Child>(); // error :'Base::Lolz' : cannot access protected member declared in class 'Base'
}

(2)使用模板专业化。

template <typename T>
int Produce()
{
  return T::Lolz();
}
class Base
{
public:
    static int Lolz()
    {
        return 0;
    }
};

class Child : public Base
{
public:
    int nothing;
};

template<>
int Produce<Child>()
{
    throw std::bad_exception("oops!");
    return 0;
}

int main(void)
{
    Produce<Base>(); // Ok.
    Produce<Child>(); // it will throw an exception!
}

答案 1 :(得分:2)

无法覆盖子类中的静态方法,只能隐藏它。也没有任何类似于强制子类提供定义的抽象方法。如果你真的需要在不同的子类中有不同的行为,那么你应该使Lolz()成为一个实例方法并正常覆盖它。

我怀疑你正在接近设计问题。面向对象设计的一个原则是替代原则。它基本上说如果B是A的子类,那么无论你在哪里使用A,它都必须是有效的。

答案 2 :(得分:1)

C ++不支持虚拟静态函数。考虑一下vtable需要支持的内容,你会意识到它是不行的。

答案 3 :(得分:0)

据我了解你的问题,你想从父类中禁用静态方法。你可以在派生类中做这样的事情:


class Child : public Base
{
public:
    int nothing;
private:
    using Base::Lolz;
};

现在Child::Lolz变为私有。 但是,当然,修复设计要好得多:)

答案 4 :(得分:0)

,或者在使用Produce ()

时可能抛出编译时错误

现代的解决方案是使用delete

class Child : public Base
{
  public:
    int nothing;
    static int Lolz() = delete;
};

它可以避免很多样板,并清楚地表达您的意图。