我现在正在学习C ++并且一直在试验课程,以便了解它们的工作方式。我现在才用Java编写类。
在我的代码中,我有一个类定义和一个要测试的驱动程序。在评论中我提到了什么有效,什么没有。我真的想知道为什么以一种方式实例化对象,但在其他方面我得到错误。它是编译器,make文件还是类代码?构造函数/默认构造函数?当我将我的代码与教科书中的其他代码进行比较时,我无法看到我出错的地方。
在Linux Mint 13上使用:code :: blocks 10.5。
标题文件:
#ifndef ENEMY_H
#define ENEMY_H
#include <string>
using namespace std;
class Enemy
{
public:
Enemy();
Enemy(int, int, string);
~Enemy();
string display();
// setter and getters:
int getHP();
void setHP(int);
int getX();
void setX(int);
int getY();
void setY(int);
string getName();
void setName(string);
private:
int hitpoints;
int x_pos;
int y_pos;
string name;
};
#endif // ENEMY_H
成员函数定义:
#include "Enemy.h"
#include <iostream>
#include <string>
// default ctor
Enemy::Enemy()
{
cout << "Creating enemy with default ctor.\n";
}
//ctor
Enemy::Enemy(int x, int y, string str)
{
cout << "Creating object with name: " << str << endl;
setX(x);
setY(y);
setHP(100);
setName(str);
}
//dtor
Enemy::~Enemy()
{
cout << "destroying Enemy: " << name << endl;
}
string Enemy::display()
{
cout<<name<<" - x: "<<x_pos<<", y: "<<y_pos<<", HP: "<<hitpoints<<endl;
}
int Enemy::getHP(){
return hitpoints;
}
void Enemy::setHP(int hp){
hitpoints = hp;
}
int Enemy::getX(){
return x_pos;
}
void Enemy::setX(int x){
x_pos = x;
}
int Enemy::getY(){
return y_pos;
}
void Enemy::setY(int y){
y_pos = y;
}
string Enemy::getName(){
return name;
}
void Enemy::setName(string objectName){
name = objectName;
}
// end of function definitions
驱动:
#include "Enemy.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Program started.\n" << endl;
// initialise a few Enemy objects
Enemy E1(1, 1, "E1");
Enemy E2(2, -4, "E2");
Enemy E3;
Enemy E4;
Enemy *E5 = new Enemy(4, 5, "E5");
E1.display(); // <- success!
E2.display(); // <- success!
E3.display(); // <- segmentation fault at run time
E4.display(); // <- segmentation fault at run time
E5.display(); // <- compile time error "request for member
// 'display'" in 'E5'. which is of
// non-class type 'enemy'
cout << "end of program.\n";
return 0;
}
答案 0 :(得分:5)
当您说Enemy E3;
时,您调用默认构造函数。它负责默认初始化您的数据成员。虽然这意味着您的std::string
成员被初始化为空字符串,但这也意味着您的其他成员未被初始化(就像执行int i; std::cout << i;
一样糟糕)。当您在输出语句中读取值时,这会导致未定义的行为,这意味着任何事情都可能发生。它选择了崩溃。
至于E5
,它是一个指针。您需要取消引用它以获取您可以使用以下内容调用成员的对象:
(*E5).display();
还有一条快捷方式可以做到这一点:
E5->display();
正如jrok指出的那样,你也不会从display
返回任何内容,即使它应该返回std::string
。对于除main
之外的每个函数,这都是未定义的行为,它将在到达右括号时返回0。
作为旁注,您有内存泄漏,因为您没有delete E5;
。在这种情况下,几乎可以肯定操作系统将负责释放内存,但将其放入循环中,您将看到内存上升和上升。
如果需要动态分配单个对象,请使用智能指针:
std::unique_ptr<Enemy> E5(new Enemy(4, 5, "E5"));
在C ++ 14中,我们也得到std::make_unique
,谢天谢地,不再需要new
。
答案 1 :(得分:5)
导致段错误的原因是您正在离开应该返回string
的函数的边缘(这是未定义的行为):
string Enemy::display()
//^^^^ you're supposed to return a string
{
cout<<name<<" - x: "<<x_pos<<", y: "<<y_pos<<", HP: "<<hitpoints<<endl;
// no return statement
}
剩下的就是@chris的答案。
答案 2 :(得分:0)
关于显示的E3和E4 seg faulting的主题,您正在尝试打印尚未初始化的变量。而你的E5是一个指针,你应该可以取消引用它来访问该方法。
答案 3 :(得分:0)
首先,不要在头文件中放置using namespace声明。在那里使用std :: string并将名称空间声明放在.cpp。
中其次,在默认构造函数中给出整数默认值(0是合理的。字符串会自动初始化为空字符串,因此除非您需要,否则不必对它们执行任何操作。
Enemy::Enemy()
{
x_pos = 0;
y_pos = 0;
...;
}
最后,E5是指向Enemy(内存中的一个位置)的指针,这意味着你必须使用箭头操作符( - &gt;)而不是。访问它的方法。