在C++中的子类中执行静态方法重载。

问题描述 投票:5回答:5

我有这样的东西。

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()方法的显式声明,或者在使用Lolz()方法时抛出一个编译时错误。Produce<Child>()?

还是说这是糟糕的OO设计,我应该做一些完全不同的事情?

EDIT:

我基本上想做的是 让这样的东西工作起来:

Manager manager;

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

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

或者,更一般地说,一个外部的抽象工厂 它不知道它所生产的对象的类型, 这样就可以在不写更多代码的情况下增加新的类型。

c++ class templates oop static
5个回答
8
投票

有两种方法可以避免。其实,这要看你想说什么。

(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!
}

2
投票

在子类中没有办法重写一个静态方法,只能隐藏它。 也没有任何类似于抽象方法的东西可以强制子类提供定义。 如果你真的需要在不同的子类中采取不同的行为,那么你应该把Lolz()做成一个实例方法,然后像正常的方法一样重写它。

我怀疑你在这里接近一个设计问题。 面向对象设计的原则之一是替换原则。 它基本上是说,如果B是A的子类,那么在任何可以使用A的地方使用B都是有效的。


1
投票

C++不支持虚拟静态函数。 想一想vtable必须是什么样子才能支持它,你就会意识到它是不可能的。


0
投票

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


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

现在... Child::Lolz 变成了private.但是,当然,修复设计会更好:)


0
投票

或者在使用Produce<Child>()时抛出一个编译时错误。

现代的解决方案是使用 delete:

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

它有助于避免大量的模板,清晰地表达你的意图。

© www.soinside.com 2019 - 2024. All rights reserved.