Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过模板的多重继承_C++_Templates_Inheritance_Multiple Inheritance_Diamond Problem - Fatal编程技术网

C++ 通过模板的多重继承

C++ 通过模板的多重继承,c++,templates,inheritance,multiple-inheritance,diamond-problem,C++,Templates,Inheritance,Multiple Inheritance,Diamond Problem,将虚拟多重继承(diamon)替换为teplates继承(linear)好吗?例如,我有一个类图: IBase / \ / \ IExtendedBase BaseImpl \ / ExtendedImpl 我知道我可以通过虚拟继承来实现它。但是我可以使用模板来使这个图线性化吗 class IBase { public: virtual std::string

将虚拟多重继承(diamon)替换为teplates继承(linear)好吗?例如,我有一个类图:

       IBase
    /          \
   /            \
IExtendedBase  BaseImpl
  \            /
   ExtendedImpl
我知道我可以通过虚拟继承来实现它。但是我可以使用模板来使这个图线性化吗

class IBase
    {
    public:
        virtual std::string name() = 0;
    };

    template<typename T>
    class BaseImpl : public T
    {
    public:
        virtual std::string name() override
        {
            return "BaseCommonImpl";
        }
    };

    template<typename T>
    class IExtendedBase : public T
    {
    public:
        virtual std::string extended_name() = 0;
    };

    template<typename T>
    class ExtendedBaseImpl : public T
    {
    public:
        virtual std::string extended_name() override
        {
            return "ExtendedBaseImpl";
        }
    };
class-IBase
{
公众:
虚拟std::string name()=0;
};
模板
类BaseImpl:public T
{
公众:
虚拟std::string name()重写
{
返回“BaseCommonImpl”;
}
};
模板
类扩展数据库:公共T
{
公众:
虚拟std::字符串扩展_name()=0;
};
模板
类ExtendedBaseImpl:public T
{
公众:
虚拟std::字符串扩展_name()覆盖
{
返回“ExtendedBaseImpl”;
}
};
现在使用typedef,我可以专门化ExtendedBase

typedef IExtendedBase<BaseImpl<IBase>> _ExtendedBase;
typedef ExtendedBaseImpl<_ExtendedBase> _ExtendedBaseImpl;
typedef IExtendedBase\u ExtendedBase;
typedef ExtendedBaseImpl _ExtendedBaseImpl;

哪种方法更好?虚拟继承还是模板继承?

这个问题是一个征求意见的问题,因此可能会被主持人关闭

在此之前,我的建议是支持避免多重继承的方法:

#include <iostream>
#include <string>

class IBase
{
public:
    virtual std::string name() = 0;
};


class IExtendedBase : public IBase
{
public:
    virtual std::string extended_name() = 0;
};


template<typename T>
class BaseImpl : public T
{
public:
    virtual std::string name() override
    {
        return "BaseCommonImpl";
    }
};

template<typename T>
class ExtendedBaseImpl : public T
{
    using inherited = T;
public:
    virtual std::string extended_name() override
    {
        return "ExtendedBaseImpl";
    }

    // optionally override name if you wish
    std::string name() override {
        return inherited::name() + "(extended)";
    }
};

typedef BaseImpl<IBase> Base;
typedef ExtendedBaseImpl<BaseImpl<IExtendedBase>> ExtendedBase;


using namespace std;

int main()
{

    Base a;
    a.name();
    cout << a.name() << endl;

    ExtendedBase b;
    cout << b.extended_name() << endl;
    cout << b.name() << endl;

}
#包括
#包括
IBase类
{
公众:
虚拟std::string name()=0;
};
类扩展数据库:公共IBase
{
公众:
虚拟std::字符串扩展_name()=0;
};
模板
类BaseImpl:public T
{
公众:
虚拟std::string name()重写
{
返回“BaseCommonImpl”;
}
};
模板
类ExtendedBaseImpl:public T
{
使用遗传=T;
公众:
虚拟std::字符串扩展_name()覆盖
{
返回“ExtendedBaseImpl”;
}
//如果愿意,可以选择覆盖名称
std::string name()重写{
返回继承的::name()+“(扩展)”;
}
};
typedef-BaseImpl-Base;
typedef ExtendedBase impl ExtendedBase;
使用名称空间std;
int main()
{
碱基a;
a、 名称();

cout虽然使用这两种不同的方法(多重继承与模板)可以获得相似的结果,但存在重要的语义差异

不幸的是,您没有提供足够的信息来推荐一个客观的选择。因此,以下是一些注意事项:

多重继承方法

多重继承是为了强制执行有效的

如果在您的情况下
ExtendedImpl
是-a
IExtendBase
,并且同时是-a
BaseImpl
,但两种继承关系都是独立的,则应首选此方法

在某些情况下(例如铸造),它会带来轻微性能开销的不便

但它的优点是允许将您的
extendedeimpl
用于可以使用它的任何基的地方。此外,它还允许动态的、基于运行时的多态性(如果它的任何基具有虚拟成员函数)

模板方法

模板用于泛型编程。如果您的
extendedeimpl
确实是泛型的,“基”是泛型概念的更多参数,而不是进一步扩展的概念,则最好使用这种方法

在这里,模板的性能会稍好一些(单继承)。但您没有实现初始模式的原始概念。而且您没有动态多态性的灵活性

如果类型之间的关系不是泛型的,您可能会在这里产生不需要的依赖关系。例如,在这里,IExtendedBase将从BaseImpl继承。在许多情况下,这可能是正常的。但在其他情况下,这可能是完全不自然的,导致在维护阶段出现持久的设计问题

结论

现在由您决定哪种优势和不便最适合您的具体情况。如果需要,您可以编辑您的问题,给出更准确的上下文和意图指示,我将修改答案
因此。

哪种方法更好?
两者都不好。这取决于。一般来说,应避免作为继承方法进行扩展,以消除这种缺陷。另请参阅《Holub on Patterns》一书因为Holub在选择实现而不是扩展方面有一些相当强烈的观点,这很有意义。多重继承只是增加了问题的数量。在我看来,你的问题似乎不是关于多重继承,而是关于一般的静态和动态继承(这是获得类似行为的完全不同的方法)。为了了解这一点,请尝试设置一个基指针向量……这对于静态方法根本不起作用。因此,通常这两种方法的组合是最方便的选择:将所有独立于派生类型的内容作为虚拟函数打包到基类中,然后从更高级别的静态继承开始一个显著的区别是:对于非模板版本,您可以使用
IExtendedBase*
IExtendedBase&
IBase*
IBase*
根据需要多态地处理
extendedeimpl
实例,而模板意味着一个只想分派到
extended\n的函数e()
需要采用
IExtendedBase*
&
类型的参数,对
BaseImpl
进行编码/限制,并使该函数对从
IExtendedBase
派生而非
BaseImpl
的任何其他类无效,除非函数本身已模板化(通常有优化和膨胀的潜力)考虑使用。