这是针对 mixin 的构造函数问题的有效解决方法吗?

发布于 2024-11-17 03:57:34 字数 1365 浏览 2 评论 0原文

据我了解,mixin 存在一个问题,如果您想使用除无参数构造函数之外的其他内容,则使用 mixin 的对象要么必须具有通用的构造函数签名,要么必须在你想要使用 mixin 的类。

这似乎是一种解决方法,尽管我不确定是否存在失败的情况。它使 mixin 的工作方式更像装饰器,但它消除了装饰器继承的公共接口的需要。我想另一个问题是语法可能会变得笨拙?

只是想知道这是否有什么可怕的危险。我也想知道,作为一个不太聪明的程序员,我是否误解了 mixin 的这个问题。

编辑:这似乎是一个更好的表述。

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(d2);
    method(d3);

    return 0;
}

无参数构造函数

装饰

x = 777 派生

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(d2);
    method(d3);

    return 0;
}

no arg constructor

decorated

x = 777 derived

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜心小果奶 2024-11-24 03:57:34
  1. 如果在构造过程中抛出异常,则会泄漏内存,
  2. 基类必须首先构造一个默认构造函数,然后再分配。

更好的做法:

Decorator(const T& initializer) : T(initializer)
{
}

并使用:

Decorator<Base> d1((Base()));
Decorator<Base> d2(Base("decorated"));
Decorator<Derived> d3(Derived("derived",777));

同样在 C++0x 中,您可以将任意数量的参数从 Decorator 的构造函数完美转发到基本构造函数,从而有效地使用法像往常一样干净:

Decorator<Base> d1;
Decorator<Base> d2("decorated");
Decorator<Derived> d3("derived",777);
  1. You're leaking memory if an exception is thrown during construction,
  2. 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);
溺渁∝ 2024-11-24 03:57:34

这就是 C++0x 包含安全转发任意数量元素的能力的原因:

template <typename T>
struct Decorator: T
{
  template <typename... Args>
  Decorator(Args&&... args): T(args...) {}
};

它干净地转发参数。在 ideone 上查看!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文