[英]C++ Expected Primary Expression Error
Player::Player(string _name, Room *starting_room)
{
name = _name;
current_room = starting_room;
}
嘗試運行/編譯“ main.cpp”時出現錯誤,在下面的構造函數中沒有看到任何錯誤。 但是我仍然遇到以下錯誤:
錯誤:“ _ name”之前的預期主表達式
錯誤:“ *”之前的預期主表達式
錯誤:無法直接調用構造函數'Player :: Player'[-fpermissive]
注意:對於函數樣式轉換,請刪除多余的':: Player'
錯誤:在此范圍內未聲明“ starting_room”
編輯1:播放器類繼承自Agent類
//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
所有錯誤消息都與您顯示在現有功能內而不是新功能開始的代碼片段一致。 因此,問題在於您在上一個函數的末尾缺少右括號。
這是您進入編譯器大腦的方式:
錯誤:“ _ name”之前的預期主表達式
這意味着編譯器希望使用類似2 + 3
的表達式,但是會看到name
。
錯誤:無法直接調用構造函數'Player :: Player'[-fpermissive]
在這里,它認為您正在嘗試調用Player::Player
函數,這與該代碼在函數內部而不是新函數一致。
注意:對於函數樣式轉換,請刪除多余的':: Player'
編譯器認為您可能正在嘗試將string* _name
轉換為Player
並使用函數風格的case Player(value)
。
如果您發布的代碼是函數主體的一部分,那么這將解釋所有這些錯誤。 編譯器不明白你為什么要編寫Player::Player(something)
,因為它使一個函數體內沒有意義的,它試圖提出其他建議,以使一個函數體內感。
第一條線索是對主要表達的討論。 對於函數聲明,您可能會看到的唯一表達式是默認參數。 但是您這里沒有人。 那么,為什么編譯器要求一個主表達式? 因為它不認為您在編寫函數聲明。 它認為您正在寫聲明。
關於您錯誤地調用函數Player::Player
的建議是您位於函數體內的另一個線索。 通常,您不能在函數主體之外調用函數。 (變量初始化是最明顯的例外。)因此,如果編譯器試圖幫助您調用函數,則它可能會認為您在函數體內。
解決此問題的另一種方法是創建一個最小的,完整的,可驗證的示例(MCVE)。 如果這樣做,您將注意到刪除先前的功能后問題就消失了。 這應該提示您以前的功能可能是問題的根源。
閱讀此 。 您絕對應該避免在標題中使用“使用命名空間”。 從每個頭文件中將其刪除。 我知道您可能總是會寫“ std ::”讓您感到痛苦,但在這種情況下,請耐心等待。
您可能想為Agent類實現參數構造函數,因此在創建Player之前設置其參數:
Agent(const std::string& _name, Room *const starting_room)
: name(_name), current_room(starting_room) { }
如果希望此構造函數可以受到保護,則只能從派生類(或朋友類)中調用它。 現在,您可以從Player構造函數的初始化部分調用此構造函數:
Player(const std::string&_name, Room *const starting_room)
: Agent(_name, starting_room) { }
注意: name和current_room在Player構造函數主體之前初始化。
這部分是關於改善代碼中的幾件事:
如果class至少具有1個虛擬方法,則它也應具有虛擬析構函數。 (由於多態性,它應該是虛擬的):
virtual ~Agent() = default;
Getter應該是const限定的,否則您將無法在const對象上調用它們:
std::string getName() const;
覆蓋虛擬功能時,請使用覆蓋說明符。 這是有用的原因,如果您嘗試覆蓋非虛函數(錯誤地),則您的代碼將無法編譯,因此可以防止出錯:
bool act(const std::string&) override;
注意: act是作為虛擬繼承的,因此它保持虛擬。 無需再次編寫。
考慮返回引用或const引用以避免不必要的復制:
const std::string& getName() const;
始終檢查標准庫中是否沒有任何實現,因此您不必從頭開始實現它。 例如toLower函數可以這樣寫:
// temp is std::string std::transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
注意: std :: transform在算法庫中
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.