在C++之中,如果要建立一个类,且类中需要有字符串数据成员,我们可以把该成员声明成两种类型。
第一种方法:使用头文件string,把字符串数据成员声明为string类的对象,用这种方法对字符串操作十分便捷,可以通过+、=、+=、==等等运算符对字符串进行拼接或判断。
第二种方法:直接把该数据成员声明为const char*类型,即一个指针。在这种情况下,一系列操作就相对麻烦,不过也能顺利得出结果。
代码示例:
//类中字符串成员进行初始化的两种方法以及友元函数的使用
#include<string>
#include<iostream>
using namespace std;
class GIRLS;//提前引用声明,因为声明友元函数output()在声明GIRLS之前
class BOYS {
private:
char* name; //姓名
int age; //年龄
char* country; //国籍
static int count;//累计人数
public:
BOYS(const char* n, int a, const char* c);/*第一种初始化字符串的方法,即用const char* 指针,
注意const不能少,否则会报错*/
~BOYS(); //用到指针必然要分配地址,注意把分配到地址消除掉
friend void output(BOYS&,GIRLS&);
};
class GIRLS {
private:
string name; //注意,与BOYS中不同,将name声明为string类的对象
int age;
string country; //注意,与BOYS中不同,将country声明为string类的对象
static int count;
public:
GIRLS(string n,int a, string c);/*第二种初始化字符串的方法,即将字符串类型声明为string类的对象*/
/* ~GIRLS()这个析构函数在这里可以不需要显示声明,用自动生成的隐式析构函数即可 */
friend void output(BOYS&,GIRLS&);
};
//以上类的声明可以换一种方式,如声明一个基类student作为模板,再声明BOYS,GIRLS对基类student进行继承,
//但是这里我们要分别演示
BOYS::BOYS(const char* n, int a, const char* c) {
name = new char[strlen(n) + 1];//+1是为了存放字符串末尾的空字符
strcpy(name, n);
age = a;
country = new char[strlen(c) + 1];
strcpy(country, c);
count++;
}
BOYS::~BOYS() {
delete []name;
delete []country;
}
GIRLS::GIRLS(string n,int a, string c) //因为在GIRLS类中把name与country声明为string类,这里的构造函数也相应地不同
{
name = n;
age = a;
country = c;
count++;
}
void output(BOYS& b, GIRLS& g) {
cout << "boys:\nname:" << b.name << " age:" << b.age << " country:" << b.country <<" count:" <<b.count<< endl;
cout << "girls:\nname:" << g.name << " age:" << g.age << " country:" << g.country <<" count:" << b.count << endl;
}
int BOYS::count = 0;//初始化静态数据成员
int GIRLS::count = 0;
int main() {
string inname2[6], incountry2[6];//建立string类对象数组存放将要输入给女生的string类数据类型成员的内容
int inage2[6];//女生年龄
cout << "Now input the information of girls" << endl;
for (int i = 0; i < 6; i++)
cin >> inname2[i] >> inage2[i] >> incountry2[i];
BOYS boys[6]{
BOYS("Peter",19,"America"),
BOYS("Martin",20,"England"),
BOYS("Mask",18,"Germany"),
BOYS("Zhang He",18,"China"),
BOYS("Wang Wei",19,"China"),
BOYS("Alan",20,"Poland")
};
GIRLS girls[6]{
GIRLS(inname2[0],inage2[0],incountry2[0]),
GIRLS(inname2[1],inage2[1],incountry2[1]),
GIRLS(inname2[2],inage2[2],incountry2[2]),
GIRLS(inname2[3],inage2[3],incountry2[3]),
GIRLS(inname2[4],inage2[4],incountry2[4]),
GIRLS(inname2[5],inage2[5],incountry2[5])
};
for(int i=0;i<6;i++)
output(boys[i], girls[i]);
return 0;
}
当然,使用const char*类型,我原本是想从输入流来导入BOYS对象的数据,但是当我建立了指针数组并想把输入流的字符串赋予它时,却出现了问题。这下面的代码段是我原来的设想:
int inage1[6];//年龄
char *inname1[6], *incountry1[6];//建立char*类型的指针数组存放将要输入给男生的char*类型数据成员的内容
cout << "Firstly input the information of boys" << endl;
for (int i = 0; i < 6; i++)
cin >> inname1[i] >> inage1[i] >> incountry1[i];//visual stdio2019此处报错,显示为使用没有初始化的内存inname[i],incountry[i];
BOYS boys[6]{
BOYS(inname1[0], inage1[0], incountry1[0]),//由于男生的构造函数中的形参为char*,int,char*,用string,int,string
BOYS(inname1[1], inage1[1], incountry1[1]),//类作为实参则会报错,表示找不到匹配的构造函数,所以要另外为男生建立
BOYS(inname1[2], inage1[2], incountry1[2]),//char*类型数组来存放输入与调用构造函数,这点十分重要
BOYS(inname1[3], inage1[3], incountry1[3]),
BOYS(inname1[4], inage1[4], incountry1[4]),
BOYS(inname1[5], inage1[5], incountry1[5])
};
在处理输入时显示我使用了未初始化的内存inname[i],incountry[i].
于是我只好先用示例中的方法处理boys这个对象的初始化,不过终归是可以运行了,结果如下:
Now input the information of girls
张小丽 18 China
Lisa 19 America
Pepper 20 America
Jane 18 England
Marry 19 France
陈芳 20 China
boys:
name:Peter age:19 country:America count:6
girls:
name:张小丽 age:18 country:China count:6
boys:
name:Martin age:20 country:England count:6
girls:
name:Lisa age:19 country:America count:6
boys:
name:Mask age:18 country:Germany count:6
girls:
name:Pepper age:20 country:America count:6
boys:
name:Zhang He age:18 country:China count:6
girls:
name:Jane age:18 country:England count:6
boys:
name:Wang Wei age:19 country:China count:6
girls:
name:Marry age:19 country:France count:6
boys:
name:Alan age:20 country:Poland count:6
girls:
name:陈芳 age:20 country:China count:6
人数统计这个点上,我没有设计好,应该再多写个成员函数打印一次总人数即可,不需要打印出这么多次count。
在我的多次尝试之下,我发现了前面提到的报错的一个解决方法:
把“char *inname1[6], *incountry1[6];”这个语句改为“char inname1[6][30], incountry1[6][30];”,这样输入流就能接收我输入的长度小于30的字符串(中间无空格,有空格的话会出错),即:
int inage1[6];
char inname1[6][30], incountry1[6][30];//修正的结果
cout << "Firstly input the information of boys" << endl;
for (int i = 0; i < 6; i++)
cin >> inname1[i] >> inage1[i] >> incountry1[i];
BOYS boys[6]{
BOYS(inname1[0], inage1[0], incountry1[0]),//对二维数组而言,诸如inname[i],incountry[i]都是地址常量,故能匹配上BOYS的构造函数对形参是const char*的要求
BOYS(inname1[1], inage1[1], incountry1[1]),
BOYS(inname1[2], inage1[2], incountry1[2]),
BOYS(inname1[3], inage1[3], incountry1[3]),
BOYS(inname1[4], inage1[4], incountry1[4]),
BOYS(inname1[5], inage1[5], incountry1[5])
};