SFML 从派生的模板调用父函数 class
SFML calling parent's function from template derived class
我正在做一个自定义项目来学习 SFML,但我遇到了问题。我想做一个 'clickable' class,我可以在其中添加一些奇特的函数,我的第一个目标是编写一个 'onMouseOver' 函数,它可能与 Javascript 中的函数几乎相同。这是 class:
template <class object>
class clickable: public object{
private:
sf::Vector2i mouse;
object& aim;
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{ target.draw(aim, states); }
public:
clickable(sf::Vector2i mouse,object& aim):mouse(mouse),aim(aim){}
bool onMouseOver(sf::Vector2i mouse) {
float width = aim.getLocalBounds().width;
float height = aim.getLocalBounds().height;
if ((mouse.x >= aim.getPosition().x) && (mouse.x <= aim.getPosition().x + width) && (mouse.y >= aim.getPosition().y) && (mouse.y <= aim.getPosition().y + height))
return true;
else return false;
}
};
这是我的主要内容:
int main()
{
sf::Font font;
if (!font.loadFromFile("arial.ttf")) {
std::cout << "Error!";
}
sf::RenderWindow window(sf::VideoMode(800, 600), "Title", sf::Style::Default);
sf::Vector2i mouse = sf::Mouse::getPosition(window);
vector<sf::Text> objects;
objects.push_back(sf::Text("Test text.", font, 14));
objects[0].setPosition(20, 20);
clickable<sf::Text> stuff(mouse,objects[0]);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
if (event.type == sf::Event::MouseMoved) {
eger = sf::Mouse::getPosition(window);
}
}
window.clear();
window.draw(stuff);
if (stuff.onMouseOver(mouse)) objects[0].setFillColor(sf::Color::Red);
else objects[0].setFillColor(sf::Color::White);
window.display();
}
return 0;}
我测试了这段代码(使用不同的变量名,因为我来自匈牙利)并且它有效。我的问题是,如果我想将“objects[0].setFillColor(sf::Color::Red)”更改为 'stuff.setFillColor(sf::Color::Red)',屏幕上什么也不会发生。我假设问题是我想从子 class 调用继承的父函数,但我不确定我能做些什么来解决这个问题。
我希望这是可以理解的,并对可能出现的语法错误感到抱歉,但正如我上面提到的,我不是母语人士。任何帮助将不胜感激!
提前致谢!
您有两个类型不同的对象 sf::Text
:
stuff
stuff
的数据成员名为 aim
调用 stuff
的 setFillColor
方法将设置 stuff
的填充颜色,而不是 aim
的。但是stuff
的draw
方法完全服从aim
的draw方法:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{ target.draw(aim, states); }
aim
不知道 stuff
的填充颜色,因此 window.draw(stuff)
将做与以前完全相同的事情。
解决方案是重新设计您的 clickable
class,这取决于您的意图。为什么您既要继承模板 class 又要拥有该 class 类型的数据成员?
现在最简单的事情可能是重新实现 sf::Text
的 setFillColor
方法作为 clickable
的新方法:
void clickable::setFillColor( const Color & color ) {
aim.setFillColor( color );
}
对于您的问题,我有一个非常快速简单的快速修复方法。在调用 target.draw(aim, states);
:
之前,只需将这行代码添加到可点击 class 的 draw
成员函数中
aim.setFillColor(this->getFillColor());
像这样:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const {
aim.setFillColor(this->getFillColor());
target.draw(aim, states);
}
或者您可以同时重载 setFillColor
和 getFillColor
成员函数:
void setFillColor(const sf::Color& c) {
aim.setFillColor(c);
}
const sf::Color& getFillColor() {
return aim.getFillColor();
}
解释:
您这样声明了一个变量 stuff
:clickable<sf::Text> stuff(mouse, objects[0]);
根据您的模板 class 定义,这意味着东西是 clickable
继承自 sf::Text
,因此它是 clickable
sf::Text
,它是还有一个sf::Text
.
正在查看您 clickable
class 的字段:
- 一个
sf::Vector2i mouse;
- a
object& aim;
,目标是 object
类型的 reference
,其中 object
是您的模板参数
因此,您的变量 stuff
包含 sf::Text
对象将包含的所有数据,因为东西是 sf::Text
、sf::Vector2i
和对一个 sf::Text
对象,不是他自己。所以在这里,你的东西对象可以访问 2 个不同的 sf::Text
对象。他自己和目标引用的人。
你draw
成员函数代码显示它绘制字段aim
,所以引用的是sf::Text
,而不是自己持有的数据
当您在代码中这样做时
objects[0].setFillColor( sf::Color::Red );
您在 stuff 对象的 aim
字段引用的对象上调用 setFillColor
方法,而 :
stuff.setFillColor(sf::Color::Red);
更改 stuff
对象本身。并且您的绘制函数将绘制对象 引用 的东西对象,但不知道应用到东西对象的所有修改
所以解决方案很简单:应用于您的 stuff
对象的所有修改都需要应用于引用的对象
当您想要绘制对象时(在 draw 方法中)或当您要求应用修改时(例如当您调用 setFillColor 方法时),您可以这样做。
顺便说一句,Alex 是对的,您的 class 设计得不是很好。您也可以不保留对 sf::Text 对象的引用并为 (*this) 调用 sf::Text draw 方法(或者只是不要在可点击对象中重载 draw 方法并正确复制 sf::Text 在你的对象中 )
谢谢两位,我明白了!两种解释都很好。我重新设计了 class,对于以下卡住的程序员,这里是我的解决方案:
template <class object>
class clickable: public object{
public:
clickable(const string& s, const sf::Font& f, unsigned int size) : object::Text(s, f, size) {}
void cmd_out() {
cout << (string) (*this).getString();
}
void graph_out(float x = 0, float y = 0) {
}
bool onMouseOver(const sf::Vector2i& eger) {
float width = (*this).getLocalBounds().width;
float height = (*this).getLocalBounds().height;
if ((eger.x >= (*this).getPosition().x) && (eger.x <= (*this).getPosition().x + width) && (eger.y >= (*this).getPosition().y) && (eger.y <= (*this).getPosition().y + height))
return true;
else return false;
}
};
现在它可以工作了,但我只能用这个 sf::Text 可点击对象制作,但如果我需要任何其他对象,可以很容易地添加另一个基于所需的构造器。
我正在做一个自定义项目来学习 SFML,但我遇到了问题。我想做一个 'clickable' class,我可以在其中添加一些奇特的函数,我的第一个目标是编写一个 'onMouseOver' 函数,它可能与 Javascript 中的函数几乎相同。这是 class:
template <class object>
class clickable: public object{
private:
sf::Vector2i mouse;
object& aim;
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{ target.draw(aim, states); }
public:
clickable(sf::Vector2i mouse,object& aim):mouse(mouse),aim(aim){}
bool onMouseOver(sf::Vector2i mouse) {
float width = aim.getLocalBounds().width;
float height = aim.getLocalBounds().height;
if ((mouse.x >= aim.getPosition().x) && (mouse.x <= aim.getPosition().x + width) && (mouse.y >= aim.getPosition().y) && (mouse.y <= aim.getPosition().y + height))
return true;
else return false;
}
};
这是我的主要内容:
int main()
{
sf::Font font;
if (!font.loadFromFile("arial.ttf")) {
std::cout << "Error!";
}
sf::RenderWindow window(sf::VideoMode(800, 600), "Title", sf::Style::Default);
sf::Vector2i mouse = sf::Mouse::getPosition(window);
vector<sf::Text> objects;
objects.push_back(sf::Text("Test text.", font, 14));
objects[0].setPosition(20, 20);
clickable<sf::Text> stuff(mouse,objects[0]);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
if (event.type == sf::Event::MouseMoved) {
eger = sf::Mouse::getPosition(window);
}
}
window.clear();
window.draw(stuff);
if (stuff.onMouseOver(mouse)) objects[0].setFillColor(sf::Color::Red);
else objects[0].setFillColor(sf::Color::White);
window.display();
}
return 0;}
我测试了这段代码(使用不同的变量名,因为我来自匈牙利)并且它有效。我的问题是,如果我想将“objects[0].setFillColor(sf::Color::Red)”更改为 'stuff.setFillColor(sf::Color::Red)',屏幕上什么也不会发生。我假设问题是我想从子 class 调用继承的父函数,但我不确定我能做些什么来解决这个问题。 我希望这是可以理解的,并对可能出现的语法错误感到抱歉,但正如我上面提到的,我不是母语人士。任何帮助将不胜感激!
提前致谢!
您有两个类型不同的对象 sf::Text
:
stuff
stuff
的数据成员名为aim
调用 stuff
的 setFillColor
方法将设置 stuff
的填充颜色,而不是 aim
的。但是stuff
的draw
方法完全服从aim
的draw方法:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{ target.draw(aim, states); }
aim
不知道 stuff
的填充颜色,因此 window.draw(stuff)
将做与以前完全相同的事情。
解决方案是重新设计您的 clickable
class,这取决于您的意图。为什么您既要继承模板 class 又要拥有该 class 类型的数据成员?
现在最简单的事情可能是重新实现 sf::Text
的 setFillColor
方法作为 clickable
的新方法:
void clickable::setFillColor( const Color & color ) {
aim.setFillColor( color );
}
对于您的问题,我有一个非常快速简单的快速修复方法。在调用 target.draw(aim, states);
:
draw
成员函数中
aim.setFillColor(this->getFillColor());
像这样:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const {
aim.setFillColor(this->getFillColor());
target.draw(aim, states);
}
或者您可以同时重载 setFillColor
和 getFillColor
成员函数:
void setFillColor(const sf::Color& c) {
aim.setFillColor(c);
}
const sf::Color& getFillColor() {
return aim.getFillColor();
}
解释:
您这样声明了一个变量 stuff
:clickable<sf::Text> stuff(mouse, objects[0]);
根据您的模板 class 定义,这意味着东西是 clickable
继承自 sf::Text
,因此它是 clickable
sf::Text
,它是还有一个sf::Text
.
正在查看您 clickable
class 的字段:
- 一个
sf::Vector2i mouse;
- a
object& aim;
,目标是object
类型的reference
,其中object
是您的模板参数
因此,您的变量 stuff
包含 sf::Text
对象将包含的所有数据,因为东西是 sf::Text
、sf::Vector2i
和对一个 sf::Text
对象,不是他自己。所以在这里,你的东西对象可以访问 2 个不同的 sf::Text
对象。他自己和目标引用的人。
你draw
成员函数代码显示它绘制字段aim
,所以引用的是sf::Text
,而不是自己持有的数据
当您在代码中这样做时
objects[0].setFillColor( sf::Color::Red );
您在 stuff 对象的 aim
字段引用的对象上调用 setFillColor
方法,而 :
stuff.setFillColor(sf::Color::Red);
更改 stuff
对象本身。并且您的绘制函数将绘制对象 引用 的东西对象,但不知道应用到东西对象的所有修改
所以解决方案很简单:应用于您的 stuff
对象的所有修改都需要应用于引用的对象
当您想要绘制对象时(在 draw 方法中)或当您要求应用修改时(例如当您调用 setFillColor 方法时),您可以这样做。
顺便说一句,Alex 是对的,您的 class 设计得不是很好。您也可以不保留对 sf::Text 对象的引用并为 (*this) 调用 sf::Text draw 方法(或者只是不要在可点击对象中重载 draw 方法并正确复制 sf::Text 在你的对象中 )
谢谢两位,我明白了!两种解释都很好。我重新设计了 class,对于以下卡住的程序员,这里是我的解决方案:
template <class object>
class clickable: public object{
public:
clickable(const string& s, const sf::Font& f, unsigned int size) : object::Text(s, f, size) {}
void cmd_out() {
cout << (string) (*this).getString();
}
void graph_out(float x = 0, float y = 0) {
}
bool onMouseOver(const sf::Vector2i& eger) {
float width = (*this).getLocalBounds().width;
float height = (*this).getLocalBounds().height;
if ((eger.x >= (*this).getPosition().x) && (eger.x <= (*this).getPosition().x + width) && (eger.y >= (*this).getPosition().y) && (eger.y <= (*this).getPosition().y + height))
return true;
else return false;
}
};
现在它可以工作了,但我只能用这个 sf::Text 可点击对象制作,但如果我需要任何其他对象,可以很容易地添加另一个基于所需的构造器。