我还在学习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中了解这些概念的人通常使用继承和多态性有任何其他提示,请告诉我们。谢谢!
答案 0 :(得分:8)
name - 在Base
中未初始化你还有另外一个问题:
Base c = Child("2");
我认为这不是你想要的。您的代码将从已铸造的Child创建Base实例。但我认为您希望使用基于Base接口的Child实例;你应该写一下:
Base *c = new Child("2");
另外,为避免将来出现错误,请将base中的析构函数声明为虚拟。
答案 1 :(得分:4)
你永远不会初始化基本的nenber变量 - 你的基础构造函数应该是:
Base(char * aname) : name( aname )
{
cout << name << ": Base class cons" << endl;
}
除此之外,当你说
时Base b = Child( "xxx" );
然后将Child实例切成一个Base,这可能不是你想要的。
答案 2 :(得分:1)
我认为您不会将成员char *名称分配给您的ctors中的任何内容。
答案 3 :(得分:1)
哇那里。
有一些问题,但你的段错误可能是因为你传递的是 char*
- 这只是一个指针,然后在{{1}中尝试cout
}。问题是,指针不在disp()
中,它位于disp()
。您可能希望深度复制main()
,或使用char*
。这样做是行不通的。
编辑:
参见编辑2
您不能只为类的std::string
变量指定名称。如果你这样做,你将得到不可预测的结果 - 你可能仍然会出现段错误。请记住:在C / C ++中,除非在堆上分配,否则对象是本地范围的。在这种情况下,在您的ctor中,您需要执行以下操作:
name
在析构函数中,你需要做类似的事情:
this->name = new char[ strlen( name ) + 1 ];
strcpy( this->name, name );
注意:我的语法可能完全错误,并且我意识到上面的代码本质上是不安全的,因为你没有检查delete [] this->name;
以确保它不是NULL,并且你没有检查返回值char*
然而,这应该让你开始。
编辑2: 我纠正了。字符串文字被视为常量存储,因此在程序的持续时间内保持不变。 然而,我相信这一课很重要:一般来说,当不处理字符串文字,传递指针(或数组等)时,你需要分配它的存储和深层复制。在销毁所述对象时,您还需要适当地取消分配。
答案 4 :(得分:1)
永远不会调用Child :: disp()方法--c是Base类型的变量,而不是指针或引用,因此它不会检查虚方法。
Base * c = new Child("1");
c->disp();
delete c;
会调用Child :: disp()。
答案 5 :(得分:0)
这里几乎没有问题。首先,你的基类析构函数必须是虚拟的。否则,即使基类析构函数指向派生对象,也将始终调用它。其次,您不应该将派生类对象分配给基类对象。这称为对象切片。 因此,赋值应该通过指针或引用来完成。
分段问题正在发生,因为它包含垃圾值。您需要在构造函数中初始化它。
答案 6 :(得分:0)
您的代码存在一些问题。
首先,你得到段错误的原因是Base ctor的实现采用了与类成员变量之一相同的参数:
class Base
{
protected:
char *name;
public:
Base(char ***name**)
{
cout << name << ": Base class cons" << endl;
}
ctor的参数'name'hides相同的类成员变量,erm ... name。
其次,你在这里slicing是你的对象:
int main()
{
//Base b;
//b.disp();
Base c = Child("2");
c.disp();
}
'c'属于Base类型,您正在尝试为其分配一个Child。当您将ogbject指定给基类时,所有Child独有的东西都会被切掉。
以下是修复这两个问题的代码:
#include <iostream>
#include <string>
using namespace std;
class Base
{
protected:
std::string name_;
public:
Base(char *name)
: name_(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 = new Child("2");
c->disp();
delete c;
}