Reputation: 379
Player::Player(string _name, Room *starting_room)
{
name = _name;
current_room = starting_room;
}
I have an error when I try to run/compile my "main.cpp", I don't see anything wrong in the constructor below. But I'm still getting this errors:
error: expected primary-expression before '_name'
error: expected primary-expression before '*'
error: cannot call constructor 'Player::Player' directly [-fpermissive]
note: for a function-style cast, remove the redundant '::Player'
error: 'starting_room' was not declared in this scope
Edit 1: Player class inherits from Agent class
//Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include<string>
#include "Room.h"
#include "Agent.h"
using namespace std;
class Player: public Agent
{
public:
Player();
Player(string _name, Room *starting_room);
virtual bool act(string direction);
};
#endif // PLAYER_H
//"Agent.h"
#ifndef AGENT_H
#define AGENT_H
#include <Room.h>
#include<string>
using namespace std;
class Agent
{
protected:
Room *current_room;
string name;
public:
Agent();
virtual bool act(string) ;
string getName();
string getCurrentRoomName();
string toLower(string temp);
Room* getCurrentRoom();
};
#endif // AGENT_H
Upvotes: 0
Views: 3539
Reputation: 542
read this. You should definitely avoid using of "using namespace" in headers. Remove it from every header file. I know you may find it pain in the ass to always write "std::", but in this case bear with it.
You might want to implement parametric costructor for Agent class, so its parameters are set before creation of Player:
Agent(const std::string& _name, Room *const starting_room)
: name(_name), current_room(starting_room) { }
If you want this constructor can be protected so it can be called only from derived classes (or friend ones). Now you can call this constructor from initialization section of Player constructor:
Player(const std::string&_name, Room *const starting_room)
: Agent(_name, starting_room) { }
Note: name and current_room are initialized before Player constructor body.
This part is about improving few things in your code:
If class has at least 1 virtual method, it should have virtual destructor as well. (it should be virtual because of polymorphism):
virtual ~Agent() = default;
Getters should be const qualified, otherwise you won't be able to call them on const objects:
std::string getName() const;
Use override specifier when overriding virtual functions. It's useful cause if you try to override non-virtual function (by mistake) your code won't compile therefore it prevents making mistakes:
bool act(const std::string&) override;
Note: act was inherited as virtual, thus it stays virtual. There's no need to write it again.
Think about returning references or const references to avoid unnecessary copying:
const std::string& getName() const;
always check if there isn't any implementation in standard libraries so you don't have to implement it .from the 'scratch'. For example toLower function can be written can be written like this:
// temp is std::string
std::transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
Note: std::transform in in algorithm library
Upvotes: 1
Reputation: 45172
All of the error messages are consistent with the code fragment you showed being written inside an existing function rather than being the start of a new function. Therefore, the problem is that you are missing a closing-brace at the end of the previous function.
Here's how you get inside the brain of the compiler:
error: expected primary-expression before '_name'
This means that the compiler expected an expression like 2 + 3
but instead it saw name
.
error: cannot call constructor 'Player::Player' directly [-fpermissive]
Here, it thinks you are trying to call the function Player::Player
which is consistent with this code being inside a function rather than being a new function.
note: for a function-style cast, remove the redundant '::Player'
The compiler thinks that you might be trying to cast string* _name
to a Player
and using the function-style case Player(value)
.
If the code you posted were part of a function body, then that would explain all of these errors. The compiler doesn't understand why you are writing Player::Player(something)
because it makes no sense inside a function body, and it's trying to suggest alternatives that would make sense inside a function body.
The first clue is the discussion of a primary expression. For a function declaration, the only place you might see a primary expression is as a default parameter. But you don't have one here. So why is the compiler asking for a primary expression? Because it doesn't think you are writing a function declaration. It think you're writing a statement.
The suggestion that you are incorrectly calling a function Player::Player
is another clue that you are inside a function body. You normally cannot call functions outside of a function body. (Variable initialization is the most notable exception.) So if the compiler is trying to help you call a function, it probably thinks you're inside a function body.
Another way to try to solve this problem is to create a minimal, complete, verifiable example (MCVE). If you had done this, you would have noticed that the problem went away when you deleted the previous function. That should tip you off that the previous function may be the source of the problem.
Upvotes: 2