我有一个名为person的非常简单的类,下面给出,我只有两个函数的问题,即setstring()函数和setname()函数,我从setname函数调用setstring()函数。
唯一的问题是在我写的主要功能中
Object.setname(“齐亚”);
结果没问题,如输出屏幕所示,
现在我写的时候
Object.setname(“Zia ur Rahman”);
没有显示任何内容,因为您可以看到输出屏幕。
我知道问题是当我将名称指针传递给setstring()函数但我对此感到困惑时请详细解释这里发生的事情。
#include<iostream.h>
class person
{
char* name;
public:
person();
void setname(const char*);
void setstring(const char*, char*);
void print()const;
};
person::person()
{
name=new char[3];
strcpy(name,"NILL");
name[3]='\0';
}
void person::setstring(const char* s, char*p)
{
if(s!=NULL)
{
delete[] p;
p=new char[strlen(s)];
strcpy(p,s);
p[strlen(s)]='\0';
}
}
void person::setname(const char* n)
{
setstring(n, name);//passing data member name
}
void person::print()const
{
cout<<"Name: "<<name<<endl;
}
main()
{
person object;
object.setname("Zia ur Rahman");
object.print();
system("pause");
}
alt text http://img264.imageshack.us/img264/8867/inheritanceimage004.jpg
alt text http://img263.imageshack.us/img263/3770/inheritanceimage003.jpg
答案 0 :(得分:3)
如果你想在C ++中进行正确的面向对象编程,你应该远离直接指针管理但是使用STL string class并使用references而不是指针。然后你应该有一个更容易的时间,你的来源应该产生正确的输出。
否则检查person类的构造函数,name-array只有3个元素,但你在那里引用第4个元素(索引0-2!)。同样在setstring()方法中,你没有为数组中的尾部'\ 0'分配足够的空间!
答案 1 :(得分:3)
没有打印任何内容的具体原因是在setstring
中,p
是名称指针的副本,而不是对它的引用。尝试将setstring
的签名更改为:
void setstring(const char* s, char*& p);
(请注意&
)。
请参阅代码中其他重要错误的其他答案 - 除非这些问题得到解决,否则您可能会遇到崩溃或奇怪的行为。
除非代码的目的仅仅是学习动态数组,否则请使用std::string
: - 。
答案 2 :(得分:2)
您是否考虑过使用STL中的std :: string?
虽然我看到的第一个问题是这个。
人::人()
{
name = new char [3];
的strcpy(名字, “NILL”);
名称[3] = '\ 0';
}
你分配一个char数组,数组的大小是3个字符,然后你用strcpy复制“NILL”,所以你用数据填充所有字符但没有null终结符\ 0。 “NILL”是一个常量字符串,因此具有隐式但未显示的空终止符,例如“NILL \ 0”。 \ 0是control character,用于表示字符串的结尾。当你访问name数组的第3个元素时,当你的数组大小是3时,你有一个超出范围的索引。
为了帮助您找出可能出错的其他部分,以下是您使用该功能的一些链接。
strcpy会将整个字符串从一个缓冲区复制到下一个缓冲区,包括空终止符控制字符。
Strlen将返回字符串的开头和终止 null字符之间的字符数。虽然它不会将空字符计为字符。这就是为什么你会看到strlen(string)+1的建议,以包含空终止符。
虽然你做得很好,但是在使用标准库函数时你会理解这些小问题。
答案 3 :(得分:2)
首先:
name=new char[3];
strcpy(name,"NILL");
name[3]='\0';
name有三个元素 - 你将它视为五个元素。以类似的方式:
p=new char[strlen(s)];
应该是:
p=new char[strlen(s) + 1];
事实上,这个功能是完全错误的 - 你应该将字符串复制到'name',而不是神秘的'p'参数。如果你真的想要那个函数,那么'p'必须是指向指针或指针引用的指针。
答案 4 :(得分:0)
假设s
有5个字符。然后new char[strlen(s)];
分配5个字符的内存。然后p[strlen(s)]='\0'
相当于p[5]=0
。这非常非常糟糕。 p[5]
不存在。
void person::setstring(const char* s, char*p)
{
if(s!=NULL)
{
delete[] p;
p=new char[strlen(s)];
strcpy(p,s);
p[strlen(s)]='\0'; //<<<< LOOK! Out of range
}
}
答案 5 :(得分:0)
比C ++代码更像是C语言。 有C ++等价物:
#include <string>
#include <iostream>
class person
{
std::string name_;
public:
person();
//preferable design is to set object invariant in appropriate constructor
explicit person(const std::string &name);
std::string get_name() const;
void set_name(const std::string &name);
void print()const;
};
person::person()
: name_("NILL")
{}
person::person(const std::string &name)
: name_(name)
{}
std::string person::get_name() const
{
return name_;
}
void person::set_name(const std::string &name)
{
name_ = name;
}
void person::print()const
{
std::cout<<"Name: "<<name_<<std::endl;
}
int main()
{
person person1;
person1.set_name("Zia ur Rahman");
person1.print();
//this is better design decision
//because after constructor we have valid object
person person2("Zia ur Rahman");
person2.print();
std::cin.get();
return 0;
}