2013-02-20 17 views
5

Zunächst möchte ich mich im Voraus entschuldigen, wenn die Antwort offensichtlich ist; Ich bin sehr neu in C++ und meine Muttersprache ist Java. Ich bin auch neu in Stack Overflow, also wenn etwas mit meiner Frage nicht stimmt oder du etwas anderes brauchst, sag es mir bitte.Seltsamer Fehler mit Standardkonstruktor (C++)

So. Ich habe dieses Stück Code hier: (I SFML für den Vektor verwenden und die 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); 

} 

Und hier ist die Kopfzeile (in die obige Datei #include):

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(); 

}; 

Als ich Erstellen Sie den Ball mit

(und ja, alle SFML-Rendering-Sachen funktioniert), wird es nie angezeigt. Ein wenig Untersuchung zeigt, dass die Variablen loc.x und loc.y nicht gesetzt sind und wahrscheinlich auch nicht der Radius, die Füllfarbe usw. des Ballobjekts. Wenn ich die Werte dieser mit std :: cout innerhalb der Konstruktor, loc.x und loc.y und alle anderen sind gesetzt, so nehme ich an, dass sie irgendwo nach dem Konstruktor nicht gesetzt werden. Was seltsam ist, dass, wenn ich den Ball mit

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

oder sogar

Ball ball(400, 300); 

alles schaffen funktioniert perfekt, und der Ball erscheint auf dem Bildschirm. Ich bin wirklich Jungs ratlos. Wenn mir jemand helfen könnte, wäre das großartig.

BTW, ich benutze OS X 10.8 mit Xcode 4.5.2 und mit SFML RC2.0, wenn das einen Unterschied macht.

Danke,

Matt

+0

Vielen Dank für die schnelle Antwort! Ich werde eine init() - Funktion erstellen, die von beiden Konstruktoren aufgerufen wird, da dies der beste Weg scheint, um das zu tun, was ich tun möchte. Der Wechsel von Java zu C++ ist sehr verwirrend. – SlEePlEs5

Antwort

2

Konstruktorverkettung nicht in C unterstützt ++ vor ++ 11 C

Sie die Logik an eine Funktion übernehmen kann und es von beiden Konstruktor aufrufen. etwas wie:

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

Konstruktorverkettung ist nicht in C++ unterstützt, wenn Sie C++ 11 verwenden, die ich nehme an, Sie sind es nicht.

Blick auf diese Antwort für Details:

LINK

3

Konstruktor in C++ Verkettungs nicht erlaubt ist, stattdessen geschehen wird hier, was ist, dass eine temporäre Version der Klasse erstellt wird, nicht zugewiesen überall, dann verworfen.

Setzen Sie stattdessen eine private Initialisierungsmethode mit den gewünschten Parametern, und rufen Sie diese von Ihren Konstruktoren mit den richtigen Parametern ab.

+1

+1 Um zu erwähnen, was die Syntax in der Frage tut, anstatt nur anzugeben, wie es funktioniert. –

+0

An den Downvoter: 1) warum, 2) danke, Sie haben gerade meine lebenslängliche Irritation über eine nicht-runde Wiederholung geheilt und haben mich so davor bewahrt, jemanden abzuweisen, um ihn abzurunden. – slugonamission

+0

Ich habe nicht abgestimmt, aber Konstruktorverkettung/Delegation ist jetzt erlaubt/möglich. Manche Leute sind nur hyperkritisch. – aggsol

1

Ich würde vorschlagen, anstelle der Konstruktorverkettung, dass Sie zweiphasige Initialisierung verwenden, was bedeutet, dass Sie eine init()-Funktion erstellen, die Sie in Ihrem Standardkonstruktor aufrufen.

6

Das Aufrufen eines Konstruktors von einem anderen Konstruktor (bekannt als Delegieren eines Konstruktors) war vor C++ 11 nicht möglich. Um es zu tun in C++ 11, müssen Sie die Mitglied der Initialisierung Liste verwenden:

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

Pre-C++ 11, können Sie eine andere Funktion erstellen, die die gemeinsame Arbeit tut und erhalten beide Konstrukteure es zu nennen.

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

anstelle einer 'init'-Funktion, die ein bisschen hässlich ist und den Neuling in Richtung ungood Zweiphasen-Konstruktion führt, ein Unterobjekt betrachten: entweder ein Datenelement oder eine Basisklasse (egal welche) –

+0

@Alf: Wenn init() ist privat, diese Lösung ist gar nicht so schlecht. – aggsol

0

Sie sollten eine init() -Methode erstellen und sie in beiden Konstruktoren aufrufen.

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

schafft eine Objekttemp Ball und zerstört sie sofort ist

1

Andere Antworten geben den syntaktisch korrekten Weg, dies zu tun.

ich etwas semantisch korrekt machen würde, so dass Sie es nennen, wie so:

Ball ball = Ball::createRandom(); 

Sie createRandom als static von Ball Funktion implementieren:

class Ball { 
public: 
    //... 
    static Ball createRandom(); 
}; 

Implementiert als:

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 Wenn Sie nicht versuchen, den Code blind zu massieren, sondern darüber nachdenken, was der Benutzer benötigt. –

+0

Danke. Ich versuche. Es ist nicht immer der richtige Weg, um Fragen zu beantworten, und es gibt nicht immer Upvotes, aber ich versuche nicht, die beste Antwort zu sein. Ich möchte den Kontext erweitern. –

Verwandte Themen