简体   繁体   中英

C++ Expected Primary Expression Error

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

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.

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:

  1. 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; 
  2. Getters should be const qualified, otherwise you won't be able to call them on const objects:

     std::string getName() const; 
  3. 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.

  4. Think about returning references or const references to avoid unnecessary copying:

     const std::string& getName() const; 
  5. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM