Is this a valid workaround to the constructor issue with mixins?
As I understand there is a problem with mixins where, if you want to use something other than a no-arg constructor, the objects you use your mixin on will either have to have a common constructor signature or you have to use initializer methods in the classes you want to use the mixin with.
This seems to be kind of a workaround, though I'm not sure if there are situations in which it would fail. It makes the mixin work more like a decorator, but it removes the need for the common interface that the decorators inherit from. I guess another problem is that the syntax might get clunky?
Just want to know if there is anything horribly dangerous about this. I also would like to know if I, being a not so smart programmer, have misunderstood this problem with mixins.
Edit: this appears to be a better formulation.
class Base
{
protected:
std::string name;
public:
Base()
{
name = "no arg constructor";
}
Base(std::string n)
{
name = n;
}
virtual void doSomething()
{
cout << name << "\n";
}
};
class Derived : public Base
{
private:
int x;
public:
Derived(std::string n, int i) : Base(n)
{
x = i;
}
void doSomething()
{
cout << "x = " << x << "\t";
Base::doSomething();
}
};
template <class T>
class Decorator : public T
{
public:
Decorator(const T& initializer) : T(initializer)
{
//*static_cast< T* >(this) = *initializer;
//delete initializer;
}
};
void method(Base& b)
{
b.doSomething();
}
int main()
{
Base b;
Decorator<Base> d1(b);
Decorator<Base> d2(Base("decorated"));
Decorator<Derived> d3(Derived("derived", 777));
method(d1);
method(d开发者_JS百科2);
method(d3);
return 0;
}
no arg constructor
decorated
x = 777 derived
- You're leaking memory if an exception is thrown during construction,
- The base class must have a default constructor to be be constructed first and then assigned.
Better do:
Decorator(const T& initializer) : T(initializer)
{
}
and use:
Decorator<Base> d1((Base()));
Decorator<Base> d2(Base("decorated"));
Decorator<Derived> d3(Derived("derived",777));
Also in C++0x you can forward perfectly any number of arguments from Decorator's constructor to the base constructor, effectively making the usage as clean as usual:
Decorator<Base> d1;
Decorator<Base> d2("decorated");
Decorator<Derived> d3("derived",777);
This is the reason why C++0x included the ability to forward, safely, an arbitrary number of elements:
template <typename T>
struct Decorator: T
{
template <typename... Args>
Decorator(Args&&... args): T(args...) {}
};
Which forwards the arguments cleanly. Check it out on ideone!
精彩评论