默认构造函数的奇怪错误(C++)
Posted
技术标签:
【中文标题】默认构造函数的奇怪错误(C++)【英文标题】:Strange bug with default constructor (C++) 【发布时间】:2013-02-20 12:52:34 【问题描述】:首先,如果答案很明显,我想提前道歉;我对 C++ 很陌生,我的第一语言是 Java。我也是 Stack Overflow 的新手,所以如果我的问题有问题或者您需要其他任何内容,请告诉我。
所以。我这里有这段代码:(我使用 SFML 作为矢量和 CircleShape)
Ball::Ball()
// This ugly thing calls the full constructor with a random x and y position
// in such a way the the entire ball is inside the screen.
Ball::Ball((rand() % (WINDOW_X - (2 * BALL_RADIUS))) + BALL_RADIUS, (rand() % (WINDOW_Y - (2 * BALL_RADIUS))) + BALL_RADIUS);
Ball::Ball(float x, float y)
loc.x = x;
loc.y = y;
ball.setPosition(loc.x - BALL_RADIUS, loc.y - BALL_RADIUS);
ball.setRadius(BALL_RADIUS);
ball.setFillColor(sf::Color::Red);
ball.setOutlineColor(sf::Color::Black);
ball.setOutlineThickness(1);
这是标题(#included 到上面的文件中):
class Ball
private:
sf::CircleShape ball;
sf::Vector2f loc;
sf::Vector2f vel;
sf::Vector2f acc;
void update();
void bounce();
void draw();
public:
Ball();
Ball(float x, float y);
void run();
;
当我用
创建球时Ball ball;
(是的,所有 SFML 渲染的东西都有效),它永远不会显示。一点调查表明,它的 loc.x 和 loc.y 变量没有设置,可能球对象的半径、填充颜色等也没有设置。如果我用 std::cout inside 打印这些值,构造函数 loc.x 和 loc.y 以及所有其他 设置,所以我假设他们得到在构造函数之后的某个地方取消设置。奇怪的是,如果我用
Ball ball((rand() % (WINDOW_X - (2 * BALL_RADIUS))) + BALL_RADIUS, (rand() % (WINDOW_Y - (2 * BALL_RADIUS))) + BALL_RADIUS);
甚至
Ball ball(400, 300);
一切正常,球出现在屏幕上。 我真的很难过伙计们。如果有人可以帮助我,那就太好了。
顺便说一句,我正在运行带有 Xcode 4.5.2 的 OS X 10.8,并使用 SFML RC2.0,如果这有什么不同的话。
谢谢,
马特
【问题讨论】:
感谢大家这么快的回复!我将创建一个由两个构造函数调用的 init() 函数,因为这似乎是做我想做的最好的方法。从 Java 迁移到 C++ 令人困惑。 【参考方案1】:在 C++11 之前,从另一个构造函数调用构造函数(称为委托构造函数)是不可能的。要在 C++11 中做到这一点,您需要使用成员初始化列表:
Ball::Ball()
: Ball((rand() % (WINDOW_X - (2 * BALL_RADIUS))) + BALL_RADIUS,
(rand() % (WINDOW_Y - (2 * BALL_RADIUS))) + BALL_RADIUS)
在 C++11 之前,您可以创建另一个函数来完成常见工作并让两个构造函数都调用它。
Ball::Ball()
init((rand() % (WINDOW_X - (2 * BALL_RADIUS))) + BALL_RADIUS,
(rand() % (WINDOW_Y - (2 * BALL_RADIUS))) + BALL_RADIUS);
Ball::Ball(float x, float y)
init(x, y);
void Ball::init(float x, float y)
loc.x = x;
loc.y = y;
ball.setPosition(loc.x - BALL_RADIUS, loc.y - BALL_RADIUS);
ball.setRadius(BALL_RADIUS);
ball.setFillColor(sf::Color::Red);
ball.setOutlineColor(sf::Color::Black);
ball.setOutlineThickness(1);
【讨论】:
而不是init
函数,它有点难看并且会导致新手走向不良的两阶段构造,而是考虑一个子对象:数据成员或基类(不管哪个)
@Alf:如果 init() 是私有的,那么该解决方案一点也不差。【参考方案2】:
C++ 11 之前的 C++ 不支持构造函数链接
您可以将逻辑带到一个函数中,并从两个构造函数中调用它。类似:
Ball::Ball()
// This ugly thing calls the full constructor with a random x and y position
// in such a way the the entire ball is inside the screen.
init((rand() % (WINDOW_X - (2 * BALL_RADIUS))) + BALL_RADIUS, (rand() % (WINDOW_Y - (2 * BALL_RADIUS))) + BALL_RADIUS);
Ball::Ball(float x, float y)
init(x,y);
Ball::init(float x, float y)
loc.x = x;
loc.y = y;
ball.setPosition(loc.x - BALL_RADIUS, loc.y - BALL_RADIUS);
ball.setRadius(BALL_RADIUS);
ball.setFillColor(sf::Color::Red);
ball.setOutlineColor(sf::Color::Black);
ball.setOutlineThickness(1);
【讨论】:
【参考方案3】:不允许在 C++ 中使用构造函数链接,而是会创建一个临时版本的类,而不是在任何地方分配,然后丢弃。
相反,使用您想要的参数创建一个私有初始化方法,并使用正确的参数从您的构造函数中调用它。
【讨论】:
+1 用于提及问题中的语法的作用,而不仅仅是说明如何使其工作。 我没有投反对票,但现在允许/可以使用构造函数链接/委托。有些人只是超级挑剔。【参考方案4】:C++ 不支持构造函数链接,除非您使用的是 C++ 11,我认为您不使用。
详情请看这个答案:
LINK
【讨论】:
【参考方案5】:我建议不要使用构造函数链接,而是使用两阶段初始化,这意味着您创建一个在默认构造函数中调用的 init()
函数。
【讨论】:
【参考方案6】:其他答案给出了执行此操作的语法正确方法。
我会做一些语义上正确的事情,以便你这样称呼它:
Ball ball = Ball::createRandom();
您将createRandom
实现为Ball
的static
函数:
class Ball
public:
//...
static Ball createRandom();
;
实现为:
int randomisePosition(int position)
return (rand() % (position - (2 * BALL_RADIUS))) + BALL_RADIUS;
Ball Ball::createRandom()
return Ball(randomisePosition(WINDOW_X),
randomisePosition(WINDOW_Y));
【讨论】:
+1 不要试图盲目地修改代码,而是考虑用户需要什么。 谢谢。我试试。这并不总是回答问题的正确方式,也并不总是得到支持,但我并不是想成为最好的单一答案。我想扩展上下文。【参考方案7】:你应该创建一个 init() 方法并在你的两个构造函数中调用它。
Ball::Ball((rand() % (WINDOW_X - (2 * BALL_RADIUS))) + BALL_RADIUS, (rand() % (WINDOW_Y - (2 * BALL_RADIUS))) + BALL_RADIUS);
创建一个临时球对象并立即销毁它
【讨论】:
以上是关于默认构造函数的奇怪错误(C++)的主要内容,如果未能解决你的问题,请参考以下文章