如何 'set' 反对多重继承中的特定基础 class?
How to 'set' object to a particular base class in multiple inheritence?
我正在尝试从 C++ 中的两个基础 classes 继承,它们具有相同的命名函数。我想要一个 class 到 'belong' 的对象到特定的基础 class,是否可以这样做?
我已经尝试过虚拟基础 class(不适合我的特定情况)并且还尝试过使用范围解析运算符但失败了。
如果可能的话,我想只使用一个 class 来做到这一点。
我已经提供了代码;
#include <SFML\Graphics.hpp>
class entity :public sf::CircleShape, public sf::RectangleShape {
public:
entity(int radius = 0) { setRadius(radius); }
entity(sf::Vector2f size) { setSize(size); }
float xspeed =0, yspeed =0;
};
entity ball(6);
entity block(10, 10);
window.draw(block); // ambiguity error as both have base class sf::drawable
window.draw(ball); // and draw function accepts sf::drawable
问题是我希望 "ball" 只是继承自 sf::CircleShape
而不是 sf::RectangleShape
。
我预计使用范围解析运算符会引用 circleshape
class 或者我可能只是用错了。
编辑:我要解决的问题是我想在 window 上绘制 "ball" 和一个矩形块,当我尝试这样做时,我会看到有歧义错误,因为它们都是可绘制的(即 sf::RectangleShape
和 sf::CircleShape
都继承自 sf::drawable
)
编辑(2):The inheritence diagram
所以函数window.draw();
接受sf::drawable
的任何对象作为参数。但是当我将圆形和矩形都继承给实体时,我收到一个歧义错误,说 base class is ambiguous
.
我知道这是死亡钻石,但是使用虚拟基础 classes 是不可能的,因为它们是 SFML 库的一部分,我不想修改它们
而不是使用继承:
直接使用直接关联:
在您的实体 class 中,您希望拥有 RectangleShape 和 CircleShape ,因此不要同时将实体 class 设为 CircleShape 和 RectangeShape,最好考虑您的实体制作一个 CircleShape 和一个 RectangleShape 的。这样你可以在你的实体 class 实例化一个 RectangeShape 和一个 CircleShape 意味着 'entity' 有一个 Rectangle 和一个 CircleShape
这是正确的做法
问题分析
class entity :public sf::CircleShape, public sf::RectangleShape
这个声明说每个 entity
同时是一个 CircleShape
和一个 RectangleShape
。这似乎不是你想要的。您似乎想要一个可以是 圆形 或 矩形的实体。所以这种继承不是正确的策略。
鉴于您正在添加水平和垂直速度,您似乎正在尝试向可以绘制的元素添加基本动画。动画是一个建立在绘图之上的抽象概念(动画必须被绘制,但并非所有的绘图都必须是动画的)。特定的移动形状将建立在动画之上,因此您理想的继承将更像是以下内容:
circle -> entity -> drawable
但是,也有一些缺点。一个缺点是这会强制所有圆圈成为动画实体,而一些圆圈可能只是在一个点上绘制。另外,圆圈和可绘制对象 classes 来自一个库,因此您不能弄乱那个特定的继承方案。
我能想到两个合理的选择。 (顺便说一句,"entity" 不是您的 class 的好名字,但为了保持一致性我会坚持使用它。您应该为 class。这将是一个很好的做法,因为命名有时是编写代码中最困难的部分之一。:) )
实体作为基础class
您可以将 entity
定义为基础 class,然后为每个形状定义一个新的 class。
--> sf::CircleShape --> sf::Drawable
/
MyCircle --<
\
--> entity
这可行,但如果 entity
需要调用 Drawable
中定义的函数,则效果不佳。并非不可能:side-cast 可以调用 Drawable
的函数。只是你必须考虑 side-cast 失败的情况,因为编译器无法捕捉到它。
作为成员的形状
我可能会做的是完全放弃继承。我不想说您的实体是一个圆圈(继承),而是采用您的实体有一个圆圈(成员资格)的方法。这种方法的一个好处是,不难将其扩展为说您的实体具有多种形状,并且都以相同的速度移动。不过,我现在会坚持使用单一形状。
这种方法的困难在于您不知道实体应该具有什么形状——它应该是圆形还是矩形?幸运的是,多态性可以很好地处理这种事情。
class entity {
std::unique_ptr<sf::Drawable> shape; // <-- Polymorphism to the rescue!
float xspeed = 0.0, yspeed = 0.0;
public:
// Construct a circle.
entity(int radius = 0) : shape(std::make_unique<sf::CircleShape>(radius)) {}
// Construct a rectangle.
entity(sf::Vector2f size) : shape(std::make_unique<sf::RectangleShape>(size)) {}
// Something will go here to support drawing.
};
要支持绘图,有(至少)两个选项。如果用 entity
作为 drop-in 替代 Drawable
是合适的,定义隐式转换可能是合理的。
operator const sf::Drawable &() const { return *shape; }
如果不需要隐式转换,可以将其标记为 explicit
。
如果您唯一需要将 entity
用作 Drawable
的时间是在您调用 window.draw()
时,您可能希望给 entity
一个 draw
方法以 window
作为参数。
void draw(sf::RenderTarget & target, sf::RenderStates states) const
{ target.draw(*shape, states); }
这使得 Drawable
可供 RenderTarget::draw()
使用,同时在其他时间不可见(减少混乱)。
我正在尝试从 C++ 中的两个基础 classes 继承,它们具有相同的命名函数。我想要一个 class 到 'belong' 的对象到特定的基础 class,是否可以这样做?
我已经尝试过虚拟基础 class(不适合我的特定情况)并且还尝试过使用范围解析运算符但失败了。
如果可能的话,我想只使用一个 class 来做到这一点。
我已经提供了代码;
#include <SFML\Graphics.hpp>
class entity :public sf::CircleShape, public sf::RectangleShape {
public:
entity(int radius = 0) { setRadius(radius); }
entity(sf::Vector2f size) { setSize(size); }
float xspeed =0, yspeed =0;
};
entity ball(6);
entity block(10, 10);
window.draw(block); // ambiguity error as both have base class sf::drawable
window.draw(ball); // and draw function accepts sf::drawable
问题是我希望 "ball" 只是继承自 sf::CircleShape
而不是 sf::RectangleShape
。
我预计使用范围解析运算符会引用 circleshape
class 或者我可能只是用错了。
编辑:我要解决的问题是我想在 window 上绘制 "ball" 和一个矩形块,当我尝试这样做时,我会看到有歧义错误,因为它们都是可绘制的(即 sf::RectangleShape
和 sf::CircleShape
都继承自 sf::drawable
)
编辑(2):The inheritence diagram
所以函数window.draw();
接受sf::drawable
的任何对象作为参数。但是当我将圆形和矩形都继承给实体时,我收到一个歧义错误,说 base class is ambiguous
.
我知道这是死亡钻石,但是使用虚拟基础 classes 是不可能的,因为它们是 SFML 库的一部分,我不想修改它们
而不是使用继承:
直接使用直接关联:
在您的实体 class 中,您希望拥有 RectangleShape 和 CircleShape ,因此不要同时将实体 class 设为 CircleShape 和 RectangeShape,最好考虑您的实体制作一个 CircleShape 和一个 RectangleShape 的。这样你可以在你的实体 class 实例化一个 RectangeShape 和一个 CircleShape 意味着 'entity' 有一个 Rectangle 和一个 CircleShape
这是正确的做法
问题分析
class entity :public sf::CircleShape, public sf::RectangleShape
这个声明说每个 entity
同时是一个 CircleShape
和一个 RectangleShape
。这似乎不是你想要的。您似乎想要一个可以是 圆形 或 矩形的实体。所以这种继承不是正确的策略。
鉴于您正在添加水平和垂直速度,您似乎正在尝试向可以绘制的元素添加基本动画。动画是一个建立在绘图之上的抽象概念(动画必须被绘制,但并非所有的绘图都必须是动画的)。特定的移动形状将建立在动画之上,因此您理想的继承将更像是以下内容:
circle -> entity -> drawable
但是,也有一些缺点。一个缺点是这会强制所有圆圈成为动画实体,而一些圆圈可能只是在一个点上绘制。另外,圆圈和可绘制对象 classes 来自一个库,因此您不能弄乱那个特定的继承方案。
我能想到两个合理的选择。 (顺便说一句,"entity" 不是您的 class 的好名字,但为了保持一致性我会坚持使用它。您应该为 class。这将是一个很好的做法,因为命名有时是编写代码中最困难的部分之一。:) )
实体作为基础class
您可以将 entity
定义为基础 class,然后为每个形状定义一个新的 class。
--> sf::CircleShape --> sf::Drawable
/
MyCircle --<
\
--> entity
这可行,但如果 entity
需要调用 Drawable
中定义的函数,则效果不佳。并非不可能:side-cast 可以调用 Drawable
的函数。只是你必须考虑 side-cast 失败的情况,因为编译器无法捕捉到它。
作为成员的形状
我可能会做的是完全放弃继承。我不想说您的实体是一个圆圈(继承),而是采用您的实体有一个圆圈(成员资格)的方法。这种方法的一个好处是,不难将其扩展为说您的实体具有多种形状,并且都以相同的速度移动。不过,我现在会坚持使用单一形状。
这种方法的困难在于您不知道实体应该具有什么形状——它应该是圆形还是矩形?幸运的是,多态性可以很好地处理这种事情。
class entity {
std::unique_ptr<sf::Drawable> shape; // <-- Polymorphism to the rescue!
float xspeed = 0.0, yspeed = 0.0;
public:
// Construct a circle.
entity(int radius = 0) : shape(std::make_unique<sf::CircleShape>(radius)) {}
// Construct a rectangle.
entity(sf::Vector2f size) : shape(std::make_unique<sf::RectangleShape>(size)) {}
// Something will go here to support drawing.
};
要支持绘图,有(至少)两个选项。如果用 entity
作为 drop-in 替代 Drawable
是合适的,定义隐式转换可能是合理的。
operator const sf::Drawable &() const { return *shape; }
如果不需要隐式转换,可以将其标记为 explicit
。
如果您唯一需要将 entity
用作 Drawable
的时间是在您调用 window.draw()
时,您可能希望给 entity
一个 draw
方法以 window
作为参数。
void draw(sf::RenderTarget & target, sf::RenderStates states) const
{ target.draw(*shape, states); }
这使得 Drawable
可供 RenderTarget::draw()
使用,同时在其他时间不可见(减少混乱)。