用teplates inheritence(线性)替换虚拟多重继承(diamon)是个好主意吗?例如,我有这个类图:
public class Pause implements MouseListener{
private Rectangle2D resumeRect;
private Rectangle2D restartRect;
public Pause(GameFrame GameFrame) {
GameFrame.addMouseListener(this);
}
public void draw(Graphics2D g) {
g.setFont(new Font("Arial", Font.BOLD, 14));
int intValue = Integer.parseInt( "ff5030",16);
g.setColor(new Color(intValue));
g.drawString("Resume", 200, 156);
resumeRect= g.getFontMetrics().getStringBounds("Resume", g);
g.drawString("Restart", 200, 172);
restartRect = g.getFontMetrics().getStringBounds("Restart", g);
g.drawString("Quit", 200, 188);
}
public void mouseClicked(MouseEvent e) {
if (resumeRect.contains(e.getPoint())) {
System.out.println("clicked");
}
System.out.println(resumeRect);
System.out.println(restartRect);
System.out.println(e.getPoint());
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
我知道我可以使用虚拟继承来实现它。但是我可以使用模板来使这个图呈线性吗?
IBase
/ \
/ \
IExtendedBase BaseImpl
\ /
ExtendedImpl
现在使用typedef我可以专门使用ExtendedBase
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";
}
};
哪种方法更好?虚拟继承或模板继承?
答案 0 :(得分:2)
虽然使用这两种不同的方法(多重继承与模板)可以获得类似的结果,但是存在重要的语义差异。
不幸的是,您没有提供足够的信息来推荐客观选择。所以这里有一些注意事项:
多重继承方法
多重继承旨在强制执行有效的 separation of concerns 。
如果在您的情况下ExtendedImpl
是 IExtendBase
并且同时 是-a,则应首选此方法 BaseImpl
,但两种继承关系都是独立的。
在某些情况下(例如,铸造)会带来轻微性能开销的不便。
但它的优点是允许在ExtendedImpl
使用任何基础的地方使用ExtendedImpl
。此外,它允许动态的,基于运行时的多态性(如果它的任何基础具有虚拟成员函数)。
模板方法
模板适用于通用编程。如果您的var_export($variable, true)
非常通用,并且“基础”是您的通用概念的更多参数,而不是进一步扩展的概念,则应优先采用此方法。
模板在这里会有稍微好一点的性能(单继承)。但是,您没有实现初始架构的原始概念。而且你没有动态多态的灵活性。
如果类型之间的关系不具有通用性,那么您可能会在此处引发不期望的依赖关系。例如,IExtendedBase将从BaseImpl继承。在许多情况下这可能没问题。但在其他情况下可能完全不自然,导致在维护阶段出现持久的设计问题。
<强>结论强>
现在由您来决定哪种优势和不便最适合您的具体情况。如果需要,您可以编辑您的问题,以更准确地指示背景和您的意图,我将调整答案 因此。
答案 1 :(得分:-1)
这个问题是对意见的要求,因此可能会被主持人关闭。
在此之前,我的建议是支持避免多重继承的方法:
#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;
}