views:

873

answers:

5

I have something like this:

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

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

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

and

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

both return 0, which is of course correct, but unwanted. Is there anyway to enforce the explicit declaration of the Lolz() method in the second class, or maybe throwing an compile-time error when using Produce<Child>()?

Or is it bad OO design and I should do something completely different?

EDIT:

What I am basically trying to do, is to make something like this work:

Manager manager;

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

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

or, more generally, an external abstract factory that doesn't know the types of objects it is producing, so that new types can be added without writing more code.

A: 

C++ doesn't support virtual static functions. Think about what the vtable would have to look like to support that and you'll realize its a no-go.

jeffamaphone
+2  A: 

There is no way to override a static method in a subclass, you can only hide it. Nor is there anything analogous to an abstract method that would force a subclass to provide a definition. If you really need different behaviour in different subclasses, then you should make Lolz() an instance method and override it as normal.

I suspect that you are treading close to a design problem here. One of the principals of object-oriented design is the substitution principal. It basically says that if B is a subclass of A, then it must be valid to use a B wherever you could use an A.

Peter Ruderman
A: 

As far as I understand your question, you want to disable static method from the parent class. You can do something like this in the derived class:


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

Now Child::Lolz becomes private. But, of course, it's much better to fix the design :)

Nikolai N Fetissov
+2  A: 

There are two ways to avoid it. Actually, it depends on what you want to say.

(1) Making Produce() as an interface of Base class.

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) Using template specialization.

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!
}
young
Thank you! Number 1 was exactly what I was looking for.
Kronikarz
A: 

*is method overloading is possible in child class?*

Rashmi