类的继承(后续内容)
继承的传递性
内容很简单,就是A继承给B,然后B又继承给C,·······
这种情况就是继承的传递,就像是先有的爷爷,然后有的爸爸,再然后才有现在的你一样,然后你可能还会有下一代,然后下一代又有下下一代等。
在C++中,类的继承也是如此,但是在程序中避免出现这样的情况,要不然类会显得很臃肿。直接上代码看看。
#include<iostream>
using namespace std;
class A
{
public:
A(string name,int age):name(name),age(age)
{
cout << "A" << endl;
}
protected:
string name;
int age;
};
class B:public A
{
public:
B(string name, int age, int money) :A(name, age), money(money)
{
cout << "B" << endl;
}
protected:
int money;
};
class C:public B
{
public:
C(string name, int age, int money, int faceScore) :B(name, age, money), faceScore(faceScore)
{
cout << "C" << endl;
}
protected:
int faceScore;
};
int main()
{
C c("小明", 20, 10000, 80);
return 0;
}
小结:
- 祖父类继承下去后,后面的类都有祖父了的属性和行为
- 创建子类对象的时候,先调用最原始的类的构造函数,然后逐层调用对应的构造函数,直到调用子类的构造函数结束,子类对象才创建好
- 显式调用构造函数只在最相关联系的两个类之间
多继承
在现实生活中,儿子是由爸爸和妈妈共同生的,那么这个儿子就同时继承了他爸爸和他妈妈的东西。
在C++中,子类也可以继承多个父类的属性和行为,然后这个子类就同时拥有了这些父类中的属性和行为。
一般写法:
写多继承时的注意点:
- 继承方式可以不同,也可以相同
- 子类可以继承任意多个父类
- 继承顺序决定调用构造函数的顺序
- 继承顺序决定调用析构函数的顺序(和构造函数相反的顺序)
代码测试:
#include<iostream>
using namespace std;
class A
{
public:
A(string name) :name_A(name)
{
cout << "A" << endl;
}
protected:
string name_A;
};
class B
{
public:
B(string name) :name_B(name)
{
cout << "B" << endl;
}
protected:
string name_B;
};
class C
{
public:
C(string name) :name_C(name)
{
cout << "C" << endl;
}
protected:
string name_C;
};
class D : protected B, public A, private C
{
public:
D(string name_A, string name_B, string name_C, string name_D) :
A(name_A), B(name_B), C(name_C)
{
this->name_D = name_D;
cout << "D" << endl;
}
protected:
string name_D;
};
int main()
{
D d("A", "B", "C", "D");
return 0;
}
继承中的特殊成员
简单回顾一下,静态是用staitc修饰的东西,属于整个类,不属于某个对象。静态数据成员在类外初始化,静态成员函数中没有this指针。
通过继承之后,父类和子类共有这个静态属性或行为。
举个简单的例子
父亲有一把砍柴刀,父亲已经用到生锈了,然后他的儿子继承了这把刀,但是这把刀并不是新的刀,还是那把已经生锈了的刀。然后他们共用这把生锈的刀。
静态数据成员
静态数据成员就是static修饰类中数据成员的成员,必须在类中声明,在类外初始化。
直接看代码:
#include<iostream>
using namespace std;
class Father
{
public:
static int knife;
Father()
{
knife++;
}
};
int Father::knife = 0;
class Son :public Father
{
public:
};
int main()
{
Father father;
cout << "父类无对象访问:" << Father::knife << endl;
cout << "父类对象访问:" << father.knife << endl;
Son son;
cout << "父类无对象访问:" << Father::knife << endl;
cout << "父类对象访问:" << father.knife << endl;
cout << "子类无对象访问:" << Son::knife << endl;
cout << "子类对象访问:" << son.knife << endl;
return 0;
}
小结:
- 静态数据成员在类中声明在类外初始化,类外初始化的时候去掉static修饰词,加类名限定
- 静态数据成员也受权限限定
- 继承下来的静态数据成员,父类和子类共用
静态成员函数
静态成员函数就是在类中使用static修饰的成员函数,可以在类中实现也可以在类外实现,静态成员函数没有this指针,因为this不知道代指谁。
那继承之后会是怎样,直接看代码
#include<iostream>
using namespace std;
class Father
{
public:
static void print()
{
cout << "Father类中的静态成员函数" << endl;
Father Cukor;
Cukor.faceScore = 100;
Cukor.money++;
cout << Cukor.faceScore << "\t"<<Cukor.money<<endl;
}
protected:
int faceScore;
static int money;
};
int Father::money = 1000;
class Son :public Father
{
public:
protected:
};
int main()
{
Father father;
Son son;
father.print();
son.print();
son.print();
father.print();
return 0;
}
小结:
- 静态成员函数可以在类中实现也可以在类外实现
- 静态成员函数没有this指针,因为this不知道代指谁。
- 静态成员函数中不能直接访问非静态数据成员
- 静态成员函数中访问类中的数据成员,只有两种方式:传参和在这个函数中创建对象,通过对象去访问才行
- 静态成员函数继承给子类后,父类和子类共用这个静态成员函数
|