假设我有一个基类和类似于以下的派生类:
#include "Sprite.h"
class Base{
private:
int X; //location
Sprite* sprite;
public:
Base(Sprite* sprite){
sprite = new Sprite(some parameter);
}
int getLocation(){
return X;
}
int getWidth(){
return sprite->getWidth();
}
}
class Derived : public Base{
private:
Sprite* sprite; // here I have to redefine it in constructor
public:
Derived(Sprite* sprite); // it's different that base constructor
{ sprite = new Sprite(some parameter);
sprite->setPriperty(some parameter);
}
}
当我从其他地方调用Derived :: getLocation()时,没有错误。但是当我调用Derived :: getWidth()时,它给了我分段错误。我必须从基类复制相同的代码(即将getWidth的代码复制到派生类中)以避免错误。我也尝试使用“使用Base :: getWidth;”,但仍然给了我分段错误。似乎如果基类方法包含指针t
答案 0 :(得分:0)
您可能忘记在构造函数中设置sprite
成员变量。执行以下操作:Base(Sprite * s): sprite(s) {}
或Base(Sprite * s) { this->sprite = s; }
。
Derived(Sprite* sprite)
构造函数应该将sprite
传递给父构造函数,如下所示:Derived(Sprite* sprite): Base(sprite) {};
请注意,Base
构造函数必须从Sprite*
的{{1}}构造函数传递有效Derived
才能处理实例getLocation()
。
答案 1 :(得分:0)
首先,什么是分段错误?这与Java中的NullPointerException
或C#中的NullReferenceException
类似。当您尝试访问未分配的内存时会发生这种情况。
为什么会这样?你忘了为sprite
指针分配内存,所以它指向一些未经精确处理的内存块。您应该使用new
运算符在构造函数中初始化它,如下所示:
Base::Base(Sprite* sprite) {
this->sprite = new Sprite(sprite);
}
如果您喜欢危险地生活,您还可以执行以下操作:
Base::Base(Sprite* sprite) {
this->sprite = sprite;
}
但它不安全,因为精灵可以在堆栈上分配,所以这样的代码可能会破坏你的程序造成不明确的行为:
Base * getBase() {
Sprite sprite;
//some code operating on sprite
return new Base(&sprite);
}
这很危险,因为在退出getBase
函数后,内存中不再有sprite
。
<强>更新强>
所以基本上我从你的评论中得出的结论是你没有调用Base
类的正确构造函数。您的Derived
构造函数应如下所示:
Derived(Sprite* sprite): Base(sprite) {
...
}
如果不这样做,则不要为基类设置sprite
的值。您派生类的sprite
字段只会隐藏sprite
类的Base
字段。就像:
int i = 0;
void fun() {
int i = 20;
}
在示例中,全局i
没有改变,因为它被遮蔽了。
您的代码在复制getWidth()
类中的Derived
方法后仍然有效,因为它正在访问sprite
类的Derived
字段。要清楚 - 不重写方法getWidth()
正在访问sprite
类的Base
字段,当您覆盖它时,它会访问Derived
类的字段。