2013-02-20 3 views
5

Прежде всего, я хотел бы извиниться заранее, если ответ очевиден; Я очень новичок в C++, и мой первый язык - это Java. Я также новичок в Stack Overflow, поэтому, если что-то не так с моим вопросом или вам нужно что-то еще, скажите мне.Странная ошибка с конструктором по умолчанию (C++)

So. У меня есть этот кусок кода здесь: (я использую 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 не установлены, и, вероятно, также не являются радиус, fillcolor и т. Д. Объекта шара. Если я напечатаю их значения с помощью std :: cout внутри, то конструктор 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); 

все работает отлично, и мяч появляется на экране. Я действительно в тупик. Если бы кто-нибудь мог мне помочь, это было бы здорово.

BTW, я использую OS X 10.8 с Xcode 4.5.2 и используя SFML RC2.0, если это имеет значение.

Спасибо,

Matt

+0

Спасибо всем за то, что вы так быстро ответили! Я создам функцию init(), вызываемую обоими конструкторами, поскольку это похоже на лучший способ сделать то, что я хочу сделать. Перемещение с Java на C++ - это смешно. – SlEePlEs5

ответ

2

Конструктор Chaining не поддерживается в 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); 

} 
2

Конструктор Chaining не поддерживается в C++, если вы не используете C++ 11, которые я предполагаю, вы не являетесь.

Посмотрите на это ответ на детали:

LINK

3

Конструктор цепочки в C++ не допускается, а не то, что будет происходить в том, что временная версия вашего класса будет создан, не назначен в любом месте, затем отбрасывается.

Вместо этого сделайте приватный метод инициализации с параметрами, которые вы хотите, и вызовите это из ваших конструкторов с правильными параметрами.

+1

+1 Для упоминания того, что делает синтаксис в вопросе, вместо того, чтобы просто указывать, как заставить его работать. –

+0

To downvoter: 1) почему, 2) спасибо, вы просто вылечили мое пожизненное раздражение от нерегулярной репутации и, таким образом, спасли меня от нисходящего кого-то другого, чтобы округлить его. – slugonamission

+0

Я не голосовал, но конструкторская цепочка/делегирование теперь разрешено/возможно. Некоторые люди просто критичны. – aggsol

1

Я бы предложил вместо цепочки конструкторов использовать двухфазную инициализацию, что означало бы создание функции init(), которую вы вызываете в своем конструкторе по умолчанию.

6

Вызов конструктора из другого конструктора (известного как делегирование конструктора) был невозможным до C++ 11. Для того, чтобы сделать это в C++ 11, вам необходимо использовать список инициализации членов:

Ball::Ball() 
: Ball((rand() % (WINDOW_X - (2 * BALL_RADIUS))) + BALL_RADIUS, 
     (rand() % (WINDOW_Y - (2 * BALL_RADIUS))) + BALL_RADIUS) 
{ } 

Pre-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); 
} 
+1

вместо функции 'init', которая является немного уродливой и ведет новичка к двухступенчатой ​​конструкции без использования, рассмотрим под-объект: либо элемент данных, либо базовый класс (не имеет значения, какой) –

+0

@Alf: Если init() является частным, это решение не так уж плохо. – aggsol

0

Вы должны сделать метод init() и вызвать его в обоих конструкторах.

Ball::Ball((rand() % (WINDOW_X - (2 * BALL_RADIUS))) + BALL_RADIUS, (rand() % (WINDOW_Y - (2 * BALL_RADIUS))) + BALL_RADIUS); 

создает объект временный мяч и уничтожает его сразу

1

Другие ответы дают синтаксически правильный способ сделать это.

Я хотел бы сделать что-то семантически правильно, так что вы называете это как так:

Ball ball = Ball::createRandom(); 

Вы реализуете createRandom как static функции Ball:

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)); 
} 
+0

+1 Для того, чтобы не пытаться слепо массировать код, а думать о том, что нужно пользователю. –

+0

Спасибо. Я попробую. Это не всегда правильный способ ответить на вопросы, и он не всегда получает поддержку, но я не стараюсь быть лучшим единственным ответом. Я хочу расширить контекст. –

Смежные вопросы