C++ C++;派生类调用基类方法给出分段错误
假设我有一个基类和派生类,如下所示:C++ C++;派生类调用基类方法给出分段错误,c++,C++,假设我有一个基类和派生类,如下所示: #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 ge
#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);
}
}
Base::Base(Sprite* sprite) {
this->sprite = sprite;
}
当我从其他位置调用派生::getLocation()时,没有错误。但是当我调用派生的::getWidth()时,它给了我分段错误。我必须从基类复制相同的代码(即将getWidth的代码复制到派生类中),以避免错误。我还尝试使用“using Base::getWidth;”,但仍然给了我分段错误。似乎如果基类方法包含指针t,您可能忘记了在构造函数中设置
sprite
成员变量。这样做:Base(Sprite*s):Sprite(s){}
或Base(Sprite*s){this->Sprite=s;}
Derived(Sprite*Sprite)
构造函数应该像这样将Sprite
传递给父构造函数:Derived(Sprite*Sprite):Base(Sprite){}代码>
请注意,就目前情况而言,基本
构造函数必须从派生
构造函数传递一个有效的Sprite*
,以便getLocation()
处理派生
的实例,因此首先-什么是分段错误?它类似于Java中的NullPointerException
,或者C#中的NullReferenceException
。当您试图访问未分配的内存时,就会发生这种情况
为什么会这样?您忘了为sprite
指针分配内存,因此它指向一些不精确的内存块。您应该使用new
操作符在构造函数中初始化它,如下所示:
Base::Base(Sprite* sprite) {
this->sprite = new Sprite(sprite);
}
Derived(Sprite* sprite): Base(sprite) {
...
}
如果你喜欢危险地生活,你也可以做以下事情:
#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);
}
}
Base::Base(Sprite* sprite) {
this->sprite = sprite;
}
但这并不安全,因为sprite可以在堆栈上分配,所以这样的代码可能会破坏程序,导致未定义的行为:
Base * getBase() {
Sprite sprite;
//some code operating on sprite
return new Base(&sprite);
}
这是危险的,因为退出getBase
函数后,内存中不再有sprite
更新:
因此,基本上我从您的评论中得出的结论是,您没有调用Base
类的正确构造函数。您的派生的构造函数应该如下所示:
Base::Base(Sprite* sprite) {
this->sprite = new Sprite(sprite);
}
Derived(Sprite* sprite): Base(sprite) {
...
}
如果不这样做,则不会为基类设置sprite
的值。派生类的sprite
字段只是隐藏了Base
类的sprite
字段。就像:
int i = 0;
void fun() {
int i = 20;
}
在本例中,全局i
没有更改,因为它被阴影遮挡
您的代码在复制派生类中的getWidth()
方法后工作,因为它当时正在访问派生类的sprite
字段。需要明确的是,在不重写方法的情况下,getWidth()
正在访问Base
类的sprite
字段,当您重写它时,它将访问派生的
类的字段。“…没有错误”-您知道。在这里定义一些理智。这里应该管理两个Sprite
实例吗?一个由Base::sprite
指向,另一个由Derived::sprite
指向?如果没有,那么您托管了太多的Sprite*
。请在你的问题中加入一个。为什么他们都有一个同名的不同的精灵?只有一个精灵类。但是,在派生类中,在初始化私有sprite成员后,必须使用sprite的方法设置一些额外的属性。因此构造函数不同于基类。因此,我必须在派生类中声明它。我们也许能帮上忙。我把代码贴出来了。如果仍然不够,我将回家获取更多的代码。如果您正在发布答案,您需要解决Sprite*的其他问题。请至少提到三条规则。:)我在基类中初始化了精灵,这是一般的移动对象。在派生类,即播放器类中,我也定义了精灵类,但不是通过基类构造函数,我只是像在基类中一样调用精灵构造函数。这很重要吗?@ohmygoddess,是的,因为当您调用getLocation()
时,它只会看到Base
类的Sprite*Sprite
。因此,像您这样做意味着它永远不会看到,因此也永远不会使用您为派生的实例创建的实例。@KennyOstrom,这就是为什么我现在有点不愿意讨论第三条规则的原因,因为似乎有一个更基本的问题“挂起,哪些成员在哪个上下文/函数中可见”。第三条规则是下一步,尽管私有/删除的副本构造函数可能更合适……所以在这种情况下,如果我声明和定义的sprite类不同于基类,那么我不能调用方法getWidth?因为没有“基”类精灵,只有“派生”类精灵?我使用new关键字初始化指针,请参阅更新的代码。如果我在派生类中复制基类的代码,一切都正常。getWidth方法。如果我在派生类中复制它,一切正常。但是我认为我不需要这样做,因为。因为inherenceSo这是否意味着如果我重写基类的私有成员,我必须重写任何调用它的方法。私有成员?我想这可能就是为什么我必须将代码复制到派生的classIt中的原因。这意味着没有什么比重写私有成员更重要的了——您只是从基类中隐藏了字段。您只是没有初始化基类中的字段,而是初始化了派生类中的字段。字段的行为不具有多态性,因此Base::getWidth()
方法正在访问sprite
字段,该字段位于Base
类中,而只有派生的
类的字段被初始化。如果你愿意