(一)派生类对象的内存空间
1.派生类对象的体积,等于基类对象的体积,再加上派生类对象自己的成员变量的体积。在派生类对象中,包含着基类对象,而且基类对象的存储位置位于派生类对象新增的成员变量之前。
2.对象存储顺序,v1,v2,v3。
class CBase{
int v1,v2;
};
class CDerived:public CBase{
int v3;
}
3.示例代码(涉及String类)
#include <iostream>
#include <string>
using namespace std;
class CStudent
{
private:
string name;
string id; //学号
char gender;//性别,'F'代表女,'M'代表男
int age;
public:
void PrintInfo();
void SetInfo( const string & name_,const string & id_,int age_, char gender_ );
string GetName() { return name; }
};
class CUndergraduateStudent:public CStudent
{//本科生类,继承了CStudent类
private:
string department; //学生所属的系的名称
public:
void QualifiedForBaoyan() { //给予保研资格
cout << "qualified for baoyan" << endl;
}
void PrintInfo() {
CStudent::PrintInfo(); //调用基类的PrintInfo
cout << "Department:" << department <<endl;
}
void SetInfo(const string & name_,const string & id_,
int age_,char gender_ ,const string & department_) {
CStudent::SetInfo(name_,id_,age_,gender_); //调用基类的SetInfo
department = department_;
}
};
void CStudent::PrintInfo()
{
cout << "Name:" << name << endl;
cout << "ID:" << id << endl;
cout << "Age:" << age << endl;
cout << "Gender:" << gender << endl;
}
void CStudent::SetInfo(const string & name_,const string & id_,
int age_,char gender_ )
{
name = name_;
id = id_;
age = age_;
gender = gender_;
}
int main()
{
CUndergraduateStudent s2;
s2.SetInfo("Harry Potter ", "118829212",19,'M',"Computer Science");
cout << s2.GetName() <<" " ;
s2.QualifiedForBaoyan ();
s2.PrintInfo ();
return 0;
}
//输出:
//Harry Potter qualified for baoyanName:Harry Potter
//ID:118829212
//Age:19Gender:M
//Department:Computer Science
补充:
(1)String对象的初始化:
– string s1("Hello"); – string month = "March"; – string s2(8,’x’);//xxxxxxxx
(2)可以将字符赋值给string对象
– string s;– s = ‘n’;
(3)输入String的方式:
cin >> stringObject; getline(cin ,s);
(4)赋值方式
string s1("cat"), s2;
s2 = s1;
string s1("cat"), s3;
s3.assign(s1);
string s1("catpig"), s3;
s3.assign(s1, 1, 3); //从s1中下标为1的字符开始复制3个字符给s3
(5)取单个字符的方式
for(int i=0;i<s1.length();i++)
cout << s1.at(i) << endl;
//成员函数at会做范围检查,如果超出范围,会抛出out_of_range异常,而下标运算符[]不做范围检查。
(6)String相连
1)string s1("good "), s2("morning! ");s1 += s2;cout << s;
2) 用成员函数 append 连接字符串
string s1("good "), s2("morning! ");
s1.append(s2);cout << s1;
s2.append(s1, 3, s1.size());//s1.size(),s1字符数
cout << s2;
// 从s1的下标3开始的s1.size()个字符添加到s2中,如果s1字符串内没有足够字符,则复
制到字符串最后一个字符
(7)比较字符串String。
1)用关系运算符比较string的大小,关系运算符包括:== , >, >=, <, <=,成立则返回true,否则返回false。
例如:
string s1("hello"),s2("hello"),s3("hell");
bool b = (s1 == s2);
cout << b << endl;//输出1。
b = (s1 == s3);
cout << b << endl;//输出0。
b = (s1 > s3);
cout << b << endl;//输出1。
2)用成员函数compare比较string的大小
string s1("hello"),s2("hello"),s3("hell");
int f1 = s1.compare(s2);
int f2 = s1.compare(s3);
int f3 = s3.compare(s1);
int f4 = s1.compare(1,2,s3,0,3); //s1 1-2; s3 0-3
int f5 = s1.compare(0,s1.size(),s3);//s1 0-end
cout << f1 << endl << f2 << endl << f3 << endl;
cout << f4 << endl << f5 << endl;
//输出 0 1 -1 -1 1。
3)成员函数substr取子串。
string s1("hello world"), s2;
s2 = s1.substr(4,5); // 下标4开始5个字符
cout << s2 << endl; //输出:o wor
4)成员函数swap交换子串。
string s1("hello world"), s2("really");
s1.swap(s2);
cout << s1 << endl;
cout << s2 << endl;
//输出:really
// hello world
5)寻找String中的字符
string s1("hello world");
s1.find("lo");
//在s1中从前向后查找 “lo” 第一次出现的地方,如果找到,返回 “lo”开始的位置,即 l 所在的位置下标。如果找不到,返回string::npos (string中定义的静态常量)
string s1("hello world");
s1.rfind("lo");
//在s1中从后向前查找 “lo” 第一次出现的地方,如果找到,返回 “lo”开始的位置,即 l 所在的位置下标。如果找不到,返回string::npos
p17略。
6)删除String中的字符串。
string s1("hello worlld");
s1.erase(5);
cout << s1<<" ";
cout << s1.length()<<" ";
cout << s1.size();
// 去掉下标 5 及之后的字符
//输出:hello 5 5
7)替换String中的字符串。
string s1("hello world");
s1.replace(2,3, "haha", 1,2);
cout << s1;
// 将s1中下标2开始的3个字符换成“haha” 中下标1开始的2个字符
// 输出:heah world
8)在String中插入字符。
string s1("hello world");
string s2(“show insert");
s1.insert(5,s2); // 将s2插入s1下标5的位置
cout << s1 << endl;
s1.insert(2,s2,5,3);
//将s2中下标5开始的3个字符插入s1下标2的位置
cout << s1 << endl;
//输出:
//helloshow insert world
//heinslloshow insert world
9)字符串拷贝copy()。
string s1("hello world");
int len = s1.length();
char * p2 = new char[len+1];
s1.copy(p2,5,0);
p2[5]=0;
cout << p2 << endl;
// s1.copy(p2,5,0) 从s1的下标0的字符开始制作一个最长5个字符长度的字符串副本并将其赋值给p2。返回值表明实际复制字符串的长度。
//输出:hello
10)字符串流处理
//字符串流处理 - 字符串输入流
istringstreamstring input("Input test 123 4.7 A");
istringstream inputString(input);
string string1, string2;
int i;double d;
char cinputString >> string1 >> string2 >> i >> d >> c;
cout << string1 << endl << string2 << endl;
cout << i << endl << d << endl << c <<endl;long L;
if(inputString >> L) cout << "long\n";else cout << "empty\n";
//输出:Inputtest1234.7Aempty字符串流处理 - 字符串输出流 istringstreamostringstream outputString;int a = 10;
outputString << "This " << a << "ok" << endl;
cout << outputString.str();
//输出:This 10
4.类之间的两种关系:继承和复合。
(1)复合关系的使用
//复合关系的使用
//正确的写法:为“狗”类设一个“业主”类的对象指针;为“业主”类设一个“狗”类的对象指针组。
class CMaster;
//CMaster必须提前声明,不能先写CMaster类后写Cdog类
class CDog {
CMaster * pm;
};
class CMaster {
CDog * dogs[10];
};
(2)基类和派生类有同名成员的情况:用这种格式base::i标明是基类的对象而不是派生类的对象。
5.派生类的构造函数
在创建派生类的对象时,需要调用基类的构造函数:初始化派生类对象中从基类继承的成员。//在执行一个派生类的构造函数之前,总是先执行基类的构造函数。
调用基类构造函数的两种方式
(1)显式方式:在派生类的构造函数中,为基类的构造函数提供参数.
derived::derived(arg_derived-list):base(arg_base-list);
包含成员对象的派生类的构造函数:
class Skill {
public:Skill(int n) { }
};
class FlyBug: public Bug {
int nWings;
Skill sk1, sk2;
public:
FlyBug( int legs, int color, int wings);
};
FlyBug::FlyBug( int legs, int color, int wings):
Bug(legs,color),sk1(5),sk2(color) ,nWings(wings) {
}
(2)隐式方式:在派生类的构造函数中,省略基类构造函数时,派生类的构造函数则自动调用基类的默认构造函数.
派生类的析构函数被执行时,执行完派生类的析构函数后,自动调用基类的析构函数。
//未结束待补充。