Using C++, I wanted to create my first C++ graphical programs by learning the SFML library through creating a Conway's Game of Life implementation. My general thought process is by first creating a simple grid of cells that have the following data just starting off: x, y, and a state (either dead or alive but is set to dead initially). However I am having difficulty understanding how to create this in SFML, coming from a Java background one can make this with relative ease using a gridlayout, however, I am not sure how to approach making a grid of cells with each cell having individual data. How would I go about creating a grid of cells with what I currently have? Here is what I have so far, bear in mind majority of the code is incomplete and additions, and subtractions to the code, will be made, however my first step is to just create a grid of cells in which if I click a cell, it should print a response in console (similar to event listeners in java):
main.cpp:
#include <iostream>
#include "Include/Grid.h"
const int32_t windowWidth = 1000; // Cols
const int32_t windowHeight = 800; // Rows
int main() {
//For testing purposes, when the program is run, the grid should pop up,
//and I should be able to place black squares on a white box grid for today
Grid gameOfLife(windowWidth, windowHeight);
gameOfLife.run();
return 0;
}
cell.h:
#ifndef CELLULARAUTOMATA2D_CELL_H
#define CELLULARAUTOMATA2D_CELL_H
#include <iostream>
#include <vector>
#include <cstdio>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
//Use enum to keep track of the state of each cell
//When grid is initialized, each cell will have a state of dead
//However when the user places the cells by clicking on the boxes,
//and clicks the "Run" button, then the program will start
class Cell {
public:
enum State {
ALIVE,
DEAD
};
private:
std::int32_t xCell;
std::int32_t yCell;
State cellState;
public:
sf::RectangleShape cell;
[[nodiscard]] int getX() const;
[[nodiscard]] int getY() const;
State getState();
void setPosition(int xPos, int yPos);
Cell(int xPos, int yPos, Cell::State state);
};
#endif //CELLULARAUTOMATA2D_CELL_H
cell.cpp:
#include "Include/Cell.h"
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
Cell::Cell(int xPos, int yPos, Cell::State state) {
this->xCell = xPos;
this->yCell = yPos;
this->cellState = state;
this->cell = sf::RectangleShape(sf::Vector2f(10,10));
cell.setFillColor(sf::Color::White);
cell.setOutlineColor(sf::Color::Black);
}
int Cell::getX() const {
return xCell;
}
int Cell::getY() const {
return yCell;
}
Cell::State Cell::getState() {
return cellState;
}
void Cell::setPosition(int xPos, int yPos) {
xCell = xPos;
yCell = yPos;
}
grid.h:
#ifndef CELLULARAUTOMATA2D_GRID_H
#define CELLULARAUTOMATA2D_GRID_H
#include <iostream>
#include <vector>
#include <cstdio>
#include "Cell.h"
class Grid {
private:
std::vector<std::vector<Cell>> gridVector;
int32_t height;
int32_t width;
bool isRunning;
public:
void initGridVector();
void setWidth(int width);
void setHeight(int height);
void placeCell();
void deleteCell();
void gridCopy();
void update();
void run();
void display(int gWidth, int gHeight) const;
Grid(int gridWidth, int gridHeight);
};
#endif //CELLULARAUTOMATA2D_GRID_H
grid.cpp:
#include "Include/Grid.h"
#include "Include/Cell.h"
#include <iostream>
#include <vector>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
Grid::Grid(int gridWidth, int gridHeight) {
this->height = gridHeight;
this->width = gridWidth;
this->isRunning = false;
}
void Grid::initGridVector() {
for(int i = 0; i < height; i++){
std::vector<Cell> cellVec;
for(int j = 0; j < width; j++){
cellVec.push_back(*new Cell(i,j,Cell::DEAD));
}
gridVector.push_back(cellVec);
}
}
void Grid::display(int gWidth, int gHeight) const {
sf::RenderWindow window(sf::VideoMode(gWidth,gHeight), "Cellular Automata");
//Run the program as long as the window is open
while (window.isOpen() && isRunning)
{
//Check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event))
{
//"close requested" event: closes the window
if (event.type == sf::Event::Closed) window.close();
}
window.clear();
for (const auto & i : gridVector){
for (const auto & j : i){
window.draw(j.cell);
}
}
window.display();
}
}
void Grid::setWidth(int gWidth) {
this->width = gWidth;
}
void Grid::setHeight(int gHeight) {
this->height = gHeight;
}
void Grid::gridCopy() {
}
void Grid::update() {
}
void Grid::deleteCell() {
}
void Grid::placeCell() {
}
void Grid::run() {
std::cout << "Automata is running" << std::endl;
isRunning = true;
initGridVector();
display(width, height);
}
The run function will basically handle all the grid functionality, (Creating the grid with initialized cells, handling event listeners such as clicking a "start" button and allowing for the user to place cells).
The problem lies in your cell class. When updating position you also must update the sf::RectangleShape cell; position because it is what really is important in drawing into the window.
It seems to you that you only have a one rect top-left corner because in reality all of them are in the same spot since the deafult position is [0,0].
In order to fix this you need to change setPosition and if you don't call it anywhere after creating and before drawing, then you also must change the constructor.
void Cell::setPosition(int xPos, int yPos) {
...
cell.setPosition(xCell,yCell);//xCell and yCell must also had been updated
}
Also I want to adress the comment:
its pretty slow (probably because I have a nested for loop within the while loop).
Yes, because you are calling many draw function in one frame (one while loop iteration), and in order to prevent that you could use sf::VertexArray. It enables you to create your own "drawing type" however, in your case you would be able to create something similar to their tilemap example but without texture.
Related
I'm trying to learn C++, and I'm making this little space-invader-like game to get better at it.
Currently everything works just fine but for some reason the performance of the game is kind of terrible considering how simple the graphics are (the game runs smoothly for a while and then stops for like half a second, constantly).
I'm pretty sure the lag is due to the amount of bullets I'm removing and creating from the vector containing them (I'm removing the bullets that go outside the screen because there's no point in updating them or rendering them). So how could I fix this?
I checked the game loop and the problem isn't there.
Code below
player.h:
#pragma once
#include <vector>
#include <iostream>
#include "entity.h"
#include "SFML/Graphics.hpp"
#include "vector.h"
class Player : public Entity {
private:
int f_lastshot = 0;
const double shoot_delay = 0.5;
const float bullet_speed = 1, speed = 0.75;
std::vector<Entity> bullets;
sf::Clock *c;
sf::Sprite bullet_sprite;
public:
Player(Vector &pos, int w, int h, sf::Sprite &spr);
~Player();
void init();
void update();
void render(Window &win);
void shoot();
};
player.cpp:
#include "player.h"
Player::Player(Vector &pos, int w, int h, sf::Sprite &spr) : Entity() {
this->pos = pos;
this->sprite = spr;
this->width = w;
this->height = h;
float scale_x = (float)w / (float)spr.getTexture()->getSize().x;
float scale_y = (float)h / (float)spr.getTexture()->getSize().y;
sprite.setScale(scale_x, scale_y);
}
void Player::update() {
if (sf::Mouse::isButtonPressed(sf::Mouse::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
if ((double)(f_lastshot / 60) > shoot_delay) // shoot only if enough time has passed
shoot();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) dir.setX(-speed); // move left
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) dir.setX(speed); // move right
else dir.setX(0); // stop if no button is being pressed
f_lastshot++;
pos = pos + dir; // add the direction to the position
for (Entity &e : bullets) {
e.update(); // update each bullet
if (e.getPos().getY() < 0) // if the bullet is outside the screen delete it
bullets.erase(bullets.begin());
}
}
void Player::render(Window &win) {
sprite.setPosition(pos.getX(), pos.getY()); // update the position of the sprite
win.render(sprite);
for (Entity &bullet : bullets)
bullet.render(win);
}
void Player::shoot() {
f_lastshot = 0;
bullets.push_back(Entity::Entity(Vector::Vector(pos.getX() + width / 2 - 8, pos.getY()), 16, 32, bullet_sprite, Vector::Vector(0,-bullet_speed)));
}
void Player::init() {
if (c == nullptr) c = new sf::Clock();
else c->restart();
dir.setX(0); dir.setY(0);
sf::Texture *bullet_texture = new sf::Texture();
if (!bullet_texture->loadFromFile("bullet.png"))
std::cerr << "Could not load bullet image" << std::endl;
bullet_sprite.setTexture(*bullet_texture);
}
Player::~Player() {
delete bullet_sprite.getTexture();
delete c;
}
entity.h:
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include "vector.h"
#include "window.h"
class Entity {
protected:
Vector pos;
sf::Sprite sprite;
int width, height;
Vector dir; // the direction
public:
Entity();
Entity(Vector &pos, int w, int h, sf::Sprite &spr);
Entity(Vector pos, int w, int h, sf::Sprite &spr);
Entity(Vector pos, int w, int h, sf::Sprite &spr, Vector dir);
void update();
void render(Window &win);
bool collides(Entity &other) const;
public:
Vector getPos() const;
Vector getDirection() const;
sf::Sprite getSprite() const;
int getWidth() const;
int getHeight() const;
void setPos(Vector &pos);
void setWidth(int width);
void setHeight(int height);
void setSize(int width, int height);
void setSprite(sf::Sprite &sprite);
void setDirection(Vector dir);
};
entity.cpp:
#include "entity.h"
Entity::Entity() {}
Entity::Entity(Vector &pos, int w, int h, sf::Sprite &spr)
: pos(pos), width(w), height(h) {
this->sprite = spr;
float scale_x = (float)w/(float)spr.getTexture()->getSize().x;
float scale_y = (float)h/(float)spr.getTexture()->getSize().y;
sprite.setPosition(pos.getX(), pos.getY());
sprite.setScale(scale_x, scale_y);
}
Entity::Entity(Vector pos, int w, int h, sf::Sprite &spr)
: pos(pos), width(w), height(h) {
this->sprite = spr;
float scale_x = (float)w / (float)spr.getTexture()->getSize().x;
float scale_y = (float)h / (float)spr.getTexture()->getSize().y;
sprite.setPosition(pos.getX(), pos.getY());
}
Entity::Entity(Vector pos, int w, int h, sf::Sprite &spr, Vector dir)
: pos(pos), width(w), height(h) {
this->sprite = spr;
this->dir = dir;
float scale_x = (float)w / (float)spr.getTexture()->getSize().x;
float scale_y = (float)h / (float)spr.getTexture()->getSize().y;
sprite.setPosition(pos.getX(), pos.getY());
}
bool Entity::collides(Entity &other) const {
bool x_coll = (pos.getX() + width> other.getPos().getX() && pos.getX()< other.getPos().getX())||(pos.getX() < other.getPos().getX() + other.getWidth() && pos.getX() > other.getPos().getX());
bool y_coll = (pos.getY() + height > other.getPos().getY() && pos.getY() < other.getPos().getY()||(pos.getY() < other.getPos().getY() + other.getHeight() && pos.getY() > other.getPos().getY()));
return (x_coll && y_coll);
}
void Entity::render(Window &win) {
sprite.setPosition(pos.getX(), pos.getY());
win.render(sprite);
}
void Entity::update() {
pos = pos + dir;
}
Vector Entity::getPos() const { return pos; }
int Entity::getWidth() const { return width; }
int Entity::getHeight() const { return height; }
sf::Sprite Entity::getSprite() const { return sprite; }
Vector Entity::getDirection() const { return dir; }
void Entity::setPos(Vector &pos) { this->pos = pos; }
void Entity::setWidth(int width) { this->width = width; }
void Entity::setHeight(int height) { this->height = height; }
void Entity::setSprite(sf::Sprite &sprite) { this->sprite = sprite; }
void Entity::setDirection(Vector dir) { this->dir = dir; }
void Entity::setSize(int width, int height) {
this->width = width;
this->height = height;
}
To identify bottlenecks and other performance issues you should use a profiler. Only by looking the code it's hard if not impossible to find the correct places that need optimisation. But one problem is indeed the way you remove bullets:
for (Entity &e : bullets) {
e.update(); // update each bullet
if (e.getPos().getY() < 0) // if the bullet is outside the screen delete it
bullets.erase(bullets.begin());
}
There is a logic error. You check if the current bullet e is outside the screen, but then delete the first one anyway. This can't be right.
It's extremely inefficient to delete the first element of a std::vector, because all the following elements will have to be moved one place left. This happens for every bullet you remove!
It may cause undefined behavior. The reference says that erase
Invalidates iterators and references at or after the point of the erase, including the end() iterator.
Changing the size of a vector while iterating over it is usually a bad idea.
To overcome those issues you could use the Erase-Remove-Idiom like this:
// Update as usual
for (Entity &e : bullets) {
e.update();
}
// Erase-Remove bullets that are out of screen
bullets.erase(std::remove_if(bullets.begin(), bullets.end(),
[](const Entity &e){ return e.getY() < 0;}), bullets.end());
I wanted to create a vector of randomly placed squares and draw them to the screen, tried passing a reference to a vector and i couldn't get that to work :(
consumable.h
#ifndef CONSUMABLE_H
#define CONSUMABLE_H
#include <SFML/Graphics.hpp>
using namespace std;
using namespace sf;
class consumable
{
public:
consumable();
virtual ~consumable();
vector<RectangleShape> fCreateConsumable(vector<RectangleShape>& vConsumable);
void fDrawTarget(float x, float y, RenderWindow &thatWindow);
protected:
private:
vector<RectangleShape> vConsumable;
RectangleShape _consumable;
};
consumable.cpp
#include "consumable.h"
consumable::consumable()
{
//ctor
}
consumable::~consumable()
{
//dtor
}
void consumable::fCreateConsumable(){
int consumableX{0}, consumableY{0};
for(int i=0;i<4;i++){
consumableX = (rand() % 31) + 1;
consumableY = (rand() % 22) + 1;
_consumable.setPosition((consumableX * 25), (consumableY * 25));
_consumable.setSize(sf::Vector2f(25.0f,25.0f));
_consumable.setFillColor(sf::Color::Magenta);
vConsumable.push_back(_consumable);
}
}
void consumable::fDrawTarget(float x, float y, RenderWindow &thatWindow){
void fCreateConsumable();
for(int i{0};i< vConsumable.size();i++){
thatWindow.draw(vConsumable[i]);
}
}
main.cpp
#include <iostream>
#include <SFML/Graphics.hpp>
#include "consumable.h"
using namespace std;
using namespace sf;
int main()
{
consumable Consumable;
RenderWindow window(VideoMode(800,750), "C++ Snake");
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
switch(event.type)
{
case Event::Closed:
window.close();
break;
default:
break;
}
}
window.clear();
Consumable.fDrawTarget(25,25,window);
window.display();
}
std::cout << "Finished" << std::endl;
return 0;
}
I wanted to loop over
Looking at your class consumable, I'd start by making _consumable local and refactor fCreateConsumable adding another function.
class consumable
{
public:
// ...
vector<RectangleShape> fCreateConsumable(vector<RectangleShape>& vConsumable);
void fDrawTarget(float x, float y, RenderWindow &thatWindow);
void UpdatePositions();
private:
vector<RectangleShape> vConsumable;
};
By removing fCreateConsumable from fDrawTarget you can avoid creating new RectangleShape, reuse the old three ones, and update them with new positions.
void consumable::UpdatePositions(){
srand(time(NULL));
for(int i{0};i< vConsumable.size();i++){
vConsumable[i].setPosition(((rand() % 31) + 1) * 25, ((rand() % 22) + 1) * 25);
}
}
void consumable::fCreateConsumable(){
int consumableX{0}, consumableY{0};
srand(time(NULL));
for(int i=0;i<4;i++){
consumableX = (rand() % 31) + 1;
consumableY = (rand() % 22) + 1;
_consumable.setPosition((consumableX * 25), (consumableY * 25));
_consumable.setSize(sf::Vector2f(25.0f,25.0f));
_consumable.setFillColor(sf::Color::Magenta);
vConsumable.push_back(_consumable);
}
}
void consumable::fDrawTarget(float x, float y, RenderWindow &thatWindow){
UpdatePositions();
for(int i{0};i< vConsumable.size();i++){
thatWindow.draw(vConsumable[i]);
}
}
Personally, I would move out UpdatePositions from fDrawTarget too and make the drawcall a const function. That way you separate the update and the rendering. If you don't, move UpdatePositions to private scope.
I am currently writing my first game (Snake) in c++ using visual Studio, I am attempting to set the blocks you eat at random areas on the screen however when I use the rand() function it says it is undefined, does anyone know why I have this error?
#include <iostream>
using namespace std;
bool gameOver;
const int WIDTH = 20;
const int HEIGHT = 20;
int x, y, foodX, foodY, score;
enum eDirection { STOP = 0, LEFT, RIGHT, UP, DOWN};
eDirection dir;
void Setup(){
gameOver = false;
dir = STOP;
x = WIDTH /2;
y = HEIGHT /2;
//rand function below is not defined??
//I thought the function was built in
foodX = rand() % WIDTH;
foodY = rand() % HEIGHT;
}
void Draw() {
}
void Input() {
}
void Logic() {
}
int main()
{
Setup();
while (!gameOver)
{
Draw();
Input();
Logic();
}
return 0;
}
You're missing an include
#include <cstdlib>
http://www.cplusplus.com/reference/cstdlib/rand/
rand is defined in the header cstdlib so you need to add this include:
#include <cstdlib>
Hey I am trying to make this space game. Now I have developed my ship, and am able to display it. However I would like to be able to use the class for more than one object. I can do this with a constructor but have no clue how to get a constructor working, what changes would I need to make to my code to make the object take an int value as a constructor and allow me to make multiple ships with the code by calling the object.
Here is my header file.
//
// Ship.hpp
// Zerg_Invasion
//
// Created by Flik Wolf on 11/9/15.
//
//
#ifndef Ship_h
#define Ship_h
#include <stdio.h>
#include "ofMain.h"
class Ship {
public:
// Constructor
Ship();
// Methods
void moveLeft();
void moveRight();
void load();
void draw();
void fire();
void keyPressed();
// Properties
int x;
int y;
ofColor color;
ofImage cat;
};
#endif
and here is my CPP file.
//
// Ship.cpp
// Zerg_Invasion
//
// Created by Flik Wolf on 11/9/15.
//
//
#include "Ship.h"
Ship::Ship() {
// Set the initial color
//color.set( ofRandom(255), ofRandom(255), ofRandom(255));
// Initial x position of the ball
x = 450;
// Initial y position of the ball
y = 200;
}
void Ship::moveLeft() {
x -= 10;
}
void Ship::moveRight() {
x += 10;
}
void Ship::load() {
cat.load("spaceShip.png");
}
void Ship::draw() {
cat.draw(x, y);
// ofCircle(x, y, 30);
}
void Ship::fire() {
ofSetColor(255, 255, 255);
ofCircle(x, 200, 2);
}
Also here is the .h and .cpp files for Openframeworks which I am using for graphics.
#pragma once
#include "ofMain.h"
#include "Ship.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mouseMoved(int x, int y);
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseEntered(int x, int y);
void mouseExited(int x, int y);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
Ship theShip;
};
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup() {
// Smooth edges
ofEnableSmoothing();
// Fixed framerate
ofSetFrameRate(120);
theShip.load();
// No need to define the initial position of the ball
// because the Ball constructor does it for you
}
//--------------------------------------------------------------
void ofApp::update() {
// theShip.move();
}
//--------------------------------------------------------------
void ofApp::draw() {
ofBackground(0);
std::vector <int> nums;
nums.push_back(0);
nums.push_back(1);
nums.push_back(3);
nums.push_back(4);
nums.push_back(5);
nums.push_back(6);
nums.push_back(7);
nums.push_back(8);
cout << nums[0] << endl;
cout << nums[1] << endl;
theShip.draw();
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key) {
if (key == 'a')
{
theShip.moveLeft();
}
if (key == 'd')
{
theShip.moveRight();
}
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key) {
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y) {
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button) {
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button) {
theShip.fire();
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button) {
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y) {
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y) {
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h) {
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg) {
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo) {
}
As mentioned, the constructor in your case should only produce one ship, and this should be the case with all object constructors.
However, it's still easy enough to create and maintain multiple ships (as you've implemented them) if you use a container like std::vector.
Containing multiple ships:
To create a container for your ships, you can use a vector like so:
std::vector<Ship> Ships;
Adding new ships:
To add additional ships to it, you can use std::vector::push_back():
Ships.push_back(Ship()); //Adds a new ship to 'Ships'
Updating the ships:
There are a couple of ways to cycle through your ships:
for (auto& i : Ships)
i.Update(); //Some updating function for each ship
Or, if you need to keep track of the specific position of each ship inside the vector:
for (unsigned int i = 0; i < Ships.size(); ++i)
Ships[i].Update() //The same updating function
How about to get the x and y as constructor argument?
in the .h file:
struct Ship {
// Constructor
Ship(int _x = 450, int _y = 200);
// ...
in the cpp file:
Ship::Ship(int _x, int _y) : x{_x}, y{_y} {
// Set the initial color
//color.set( ofRandom(255), ofRandom(255), ofRandom(255));
}
Okay, I've been running into some inconsistency and it's driving me towards a fist-sized hole in my moniter I'd rather avoid.
I'm going through an SDL tutorial on www.sdltutorials.com (the sdl-tutorial-basics tutorial I'm sure more than a few people have gone through by Tim Jones) and I ran into an error: ‘Surf_Display’ was not declared in this scope.
So, trying to figure out what's going wrong I wrote similar pointer code into an old rectangle program I used to refresh myself with the basics of C++ classes, saw the same error with an int pointer, and then tried to isolate the issue in something more specific.
Well, the more specific program compiles fine while the others explode so I'm guessing it's something pretty basic I'm missing, but GISing "C++ pointer class", etc, does nothing and I don't know how to get more specific.
Anyway...some code.
The program that works...
ct.h
#ifndef _CT_H_
#define _CT_H_
class Classtest2
{
private:
int *p_x;
public:
Classtest2();
void set_x(int);
int get_x();
};
#endif
ct.cpp
#include "ct.h"
#include <cstddef>
Classtest2::Classtest2()
{
p_x = 0;
}
void Classtest2::set_x(int x)
{
//do something neat here
}
int Classtest2::get_x()
{
return *p_x;
}
classtest2.cpp
#include "ct.h"
int main (int argc, char *argv[])
{
Classtest2 ct2;
return 0;
}
compiled with
g++ classtest2.cpp ct.h ct.cpp -o bin/classtest2
Now...the program that doesn't...
The classic...
#ifndef _RECTANGLE_H
#define _RECTANGLE_H
namespace shapes
{
class rectangle
{
public:
int height;
int width;
int *weight;
rectangle (int, int);
rectangle ();
int area ();
void setHeight(int);
void setWidth(int);
void setDimensions(int, int);
};
}
#endif
The classic cpp with weight...
#include "Rectangle.h"
#include <cstddef>
using namespace shapes;
rectangle::rectangle(int h, int w)
{
height = h;
width = w;
weight = NULL;
}
rectangle::rectangle()
{
height = 0;
width = 0;
weight = NULL;
}
int rectangle::area ()
{
return height * width;
}
void rectangle::setHeight(int h)
{
height = h;
}
void rectangle::setWidth(int w)
{
width = w;
}
void rectangle::setDimensions(int h, int w)
{
height = h;
width = w;
}
And the classic "do something simple" main...
#include "Rectangle.h"
#include <iostream>
using namespace std;
using namespace shapes;
int main(int argc, char* argv[])
{
rectangle tr(5,8);
cout << tr.height << endl;
cout << tr.width << endl;
return 0;
}
The first program compiles fine, but of course it doesn't actually do anything so that's not too surprizing. The second one (the rectangle program that also doesn't actually do anything) doesn't compile. I get the following...
g++ classtest1.cpp Rectangle.h Rectangle.cpp -o bin/classtest1
Rectangle.cpp: In constructor ‘shapes::rectangle::rectangle(int, int)’:
Rectangle.cpp:10: error: ‘weight’ was not declared in this scope
Rectangle.cpp: In constructor ‘shapes::rectangle::rectangle()’:
Rectangle.cpp:17: error: ‘weight’ was not declared in this scope
So, why can the first program "see" int *p_x while the second cannot see int *weight? I've been trying to figure out what I'm doing different and getting nowhere.
The right syntax for Rectangle.cpp is this:
#include "Rectangle.h"
#include <cstddef>
namespace shapes {
rectangle::rectangle(int h, int w)
{
height = h;
width = w;
weight = NULL;
}
rectangle::rectangle()
{
height = 0;
width = 0;
weight = NULL;
}
int rectangle::area ()
{
return height * width;
}
void rectangle::setHeight(int h)
{
height = h;
}
void rectangle::setWidth(int w)
{
width = w;
}
void rectangle::setDimensions(int h, int w)
{
height = h;
width = w;
}
} // namespace shapes
My GCC-4.4.5 and MSVC process your using namespace variant OK too. But it is not correct according to the current standard (you specify ::rectangle::area(), etc. instead of ::shapes::rectangle::area(), etc.).
You don't have errors in the code you've shown. Maybe you have a typo in int *wight declaration in Rectangle.h on your machine, but you've posted the correct code here.