为什么在这段代码中调用虚拟方法时会出现分段错误?
我还在学习C++; 我正在尝试多态性的工作原理,并且在调用虚拟方法时遇到分段错误。
(注意:我没有将析构函数标记为虚拟,我只是想看看会发生什么。)这是代码:
#include <iostream>
using namespace std;
class Base
{
protected:
char *name;
public:
Base(char *name)
{
cout << name << ": Base class cons" << endl;
}
~Base()
{
cout << name << ": Base class des" << endl;
}
virtual void disp();
};
void Base::disp()
{
cout << name << ": Base disp()" << endl;
}
class Child : public Base
{
public:
Child(char *name):
Base(name)
{
cout << name << ": Child class cons" << endl;
}
~Child()
{
cout << name << ": Child class des" << endl;
}
virtual void disp()
{
cout << name << ": Child disp()" << endl;
}
};
int main()
{
//Base b;
//b.disp();
Base c = Child("2");
c.disp();
}
另外,如果您对了解继承和多态性的使用有任何其他提示, Java中的这些概念,请告诉我。 谢谢你!
I'm still learning C++; I was trying out how polymorphism works and I got a segmentation fault when calling a virtual method.
(Note: I didn't mark the destructor as virtual, I was just trying out to see what happens.) Here's the code:
#include <iostream>
using namespace std;
class Base
{
protected:
char *name;
public:
Base(char *name)
{
cout << name << ": Base class cons" << endl;
}
~Base()
{
cout << name << ": Base class des" << endl;
}
virtual void disp();
};
void Base::disp()
{
cout << name << ": Base disp()" << endl;
}
class Child : public Base
{
public:
Child(char *name):
Base(name)
{
cout << name << ": Child class cons" << endl;
}
~Child()
{
cout << name << ": Child class des" << endl;
}
virtual void disp()
{
cout << name << ": Child disp()" << endl;
}
};
int main()
{
//Base b;
//b.disp();
Base c = Child("2");
c.disp();
}
Also, if you've any other tips regarding the usage of inheritance and polymorphism in general for someone who knows these concepts in Java, please let me know. Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
name - 在 Base 中未初始化,
您还有另一个问题:
我认为这不是您想要的。 您的代码将从已转换的 Child 创建 Base 的实例。 但我认为你想使用基于 Base 接口的 Child 实例; 你应该写:
另外,为了避免未来的错误,将基类中的析构函数声明为虚拟的。
name - is unintialized in Base
also you have another problem:
I don't think it's what you want. Your code will create an instance of Base from casted Child. But I think you want work with Child instance based on Base interface; you should instead write:
also, to avoid future bugs, declare destructor in base as virtual.
您永远不会初始化基本 nenber 变量 - 您的基本构造函数应该是:
除此之外,当您说
那么 Child 实例将被切片为 Base 时,这可能不是您想要的。
You never initialise the base nenber variable - your base constructor should be:
As well as that, when you say
then the Child instance will be sliced down to a Base, which is probably not what you want.
我认为您没有将成员 char * 名称分配给您的 ctors 中的任何内容。
I don't think you're assigning the member char * name to anything in your ctors.
Child::disp() 方法永远不会被调用 - c 是 Base 类型的变量,而不是指针或引用,因此它不会检查虚拟方法。
会调用 Child::disp()。
The Child::disp() method will never be called - c is a variable of type Base, and not a pointer or reference, so it won't check for virtual methods.
would call Child::disp().
哇在那里。
有一些问题,
但是你的段错误可能是因为你传递了一个char*
——它只是一个指针,然后尝试cout
它disp()
。 问题是,该指针并不存在于disp()
中,而是存在于main()
中。 您可能想要深度复制char*
,或使用std::string
。 这样做是行不通的。编辑:
参见编辑2
您不能只将名称分配给类的
name
变量。 如果你这样做,你会得到不可预测的结果 - 并且你可能仍然会出现段错误。 请记住:在 C/C++ 中,对象的作用域是本地的,除非在堆上分配。 在这种情况下,在您的构造函数中,您需要执行以下操作:在析构函数中,您需要执行以下操作:
注意:我的语法可能完全错误,并且我意识到上面的代码本质上是不安全的,因为您没有检查
char*
以确保它不为 NULL,也没有检查new 的返回值。
尽管如此,这应该可以帮助您开始。编辑2:
我纠正了。 字符串文字被视为常量存储,因此在程序运行期间一直存在。 尽管如此,我认为这个教训很重要:一般来说,当不处理字符串文字时,传递指针(或数组等)时,您需要分配它的存储和深复制。 在销毁所述对象时,您还需要适当地取消分配。
Whoa there.
There's a few problems,
but your segfault is probably because you're passing achar*
-- which is just a pointer, and then trying tocout
it indisp()
. Problem is, that pointer does not live indisp()
, it lives inmain()
. You probably want to either deep-copy thechar*
, or usestd::string
. Doing it this way will not work.EDIT:
See EDIT 2
You can not just assign name to the class's
name
variable. If you do that, you'll get unpredictable results - and you'll probably STILL segfault. Remember: in C/C++, objects are locally scoped unless allocated on the heap. In this case, in your ctor, you'd want to do something like:And in the destructor, you'll want to do something like:
Note: my syntax may be completely wrong, and I realize the above code is inherently unsafe as you're not checking the
char*
to make sure it's not NULL, and you're not checking the return value ofnew.
Nevertheless, this should get you started.EDIT 2:
I stand corrected. String literals are treated as constant storage and thus live on for the duration of the program. Nevertheless, the lesson, I believe, is important: in general, when not dealing with string literals, passing a pointer (or array, etc.), you need to allocate storage for it and deep-copy. You also need to de-allocate appropriately when destroying said object.
这里几乎没有问题。 首先,你的基类析构函数必须是虚拟的。 否则,即使基类析构函数指向派生对象,也将始终被调用。 其次,不应将派生类对象分配给基类对象。 这称为对象切片。
因此,赋值应该通过指针或引用来完成。
发生分段问题是因为它包含垃圾值。 您需要在构造函数中对其进行初始化。
There are few problems here. The first thing is your base class destructor has to be virtual. Otherwise your base class destructor will always be called even if it points to derived object. Second is you should not assign derived class object to base class object. This is called object slicing.
So, assignment should be done through pointer or reference.
The segmentation problem is happening because it contains garbage value. You need to initialize it in the constructor.
您的代码存在一些问题。
首先,您遇到段错误的原因是 Base ctor 的实现采用与类成员变量之一同名的参数:
ctor 的参数“name”隐藏该类' 相同的成员变量,呃...名称。
其次,您在此处切片您的对象:
'c'是输入 Base,并且您正在尝试为其分配一个 Child。 当您将 ogbject 分配给基类时,Child 特有的所有内容都将被删除。
这是解决这两个问题的代码:
You have a couple of problems with your code.
First, and the reason why your getting a segfault, is the implementation of the Base ctor takes a parameter of the same name as one of the class' member variables:
The ctor's parameter 'name' hides the class' member variable of the same, erm... name.
Second, you are slicing your object here:
'c' is of type Base, and you are trying to assign a Child to it. All of the stuff that is unique to Child will be sliced off when you assign the ogbject to the base class.
Here is code that fixes both these problems: