- 一、继承访问权限测试
- 设计类A具有public, protected, private等不同属性的成员函数或变量;
- 类B通过public, protected, private等不同方式继承A,在类B的成员函数中测试访问A的成员函数或变量;
- 在类A中添加public, protected, private等不同属性的成员函数或变量,在外部测试访问A的各个成员函数或变量;
- B以private方式继承A,尝试把A中的部分public成员提升为public。
- 二、友元类继承测试
- 设计类A含有私有变量a,在类A中友元给类C;
- 设计类B继承A,添加私有变量b;在类C中测试访问类B的成员变量a, b;
- 设计类D继承C,在D的成员函数中测试访问类A的成员变量a,类B的成员变量a, b。
- 三、多态性综合运用
- 一般多态性函数:输入输出参数完全一样,在父类中添加virtual;
- 特殊多态性函数:输入或输出参数在子类中是父类的指针或基类的引用,在子类中对于的是子类的指针或子类的引用;
- 析构函数的多态性;
- 多继承,注意什么情况需要虚继承;
- 结语
- 结语
class A
{
private:
int pri_a;
protected:
int pro_a;
public:
A();
int pub_a;
friend class C;
virtual void name() {
cout << "i am A" << endl;
}
};
类B通过public, protected, private等不同方式继承A,在类B的成员函数中测试访问A的成员函数或变量;
class B1 :virtual public A {
public:
int pub_b1 = 5;
void call() { //测试A中成员
//pri_a = 1; error
pro_a = 2;
pub_a = 3;
}
void name() { //重载A中的函数
cout << "i am B1" << endl;
}
private:
int pri_b1 = 4;
protected:
int pro_b1 = 6;
};
class B2 :protected A {
public:
void call() { //测试A中成员
//pri_a = 1; error
pro_a = 2;
pub_a = 3;
}
};
class B3 :private A
{
public:
using A::pub_a;//在B3中提升A的public成员为public
void call() { //测试A中成员
//pri_a = 1; error
pro_a = 2;
pub_a = 3;
}
};
在类A中添加public, protected, private等不同属性的成员函数或变量,在外部测试访问A的各个成员函数或变量;
A a; cout << a.pub_a << endl;//在外部访问A的各个成员;pub_a可以访问到 //cout << a.pri_a<B以private方式继承A,尝试把A中的部分public成员提升为public。
class B3 :private A
{
public:
using A::pub_a;//在B3中提升A的public成员为public
void call() { //测试A中成员
//pri_a = 1; error
pro_a = 2;
pub_a = 3;
}
};
二、友元类继承测试
设计类A含有私有变量a,在类A中友元给类C;
class A
{
private:
int pri_a;
protected:
int pro_a;
public:
A();
int pub_a;
friend class C; //友元
virtual void name() {
cout << "i am A" << endl;
}
};
设计类B继承A,添加私有变量b;在类C中测试访问类B的成员变量a, b;
class C {
public:
B1 b1;
void call() {
b1.pri_a = 1;//可以访问到朋友A的那部分成员(特殊)
//b1.pro_b1 = 1; 访问不到专属于A的子类B1的private,protected成员。
//b1.pri_b1 = 4;
}
};
可以知道父亲的朋友与这个儿子毫无关系。
设计类D继承C,在D的成员函数中测试访问类A的成员变量a,类B的成员变量a, b。class D :public C {
public:
A a;
B1 b1;
void visit() { //可得到friend无法继承
//a.pri_a = 1; 访问不到
//a.pro_a = 2; 访问不到
//b1.pri_b1 = 1; 访问不到
}
};
三、多态性综合运用
一般多态性函数:输入输出参数完全一样,在父类中添加virtual;
如以下name();
class A
{
private:
int pri_a;
protected:
int pro_a;
public:
A();
int pub_a;
friend class C;
virtual void name() { //虚函数
cout << "i am A" << endl;
}
};
class B1 :virtual public A {
public:
~B1(){
cout<<"destroy B1"<
特殊多态性函数:输入或输出参数在子类中是父类的指针或基类的引用,在子类中对于的是子类的指针或子类的引用;
多加三个用于调用A的函数
//.h
void outCall1(A& p);
void outCall1(A* p);
void outCall2(A p);
//.cpp
void outCall1(A& p){
p.name();
}
void outCall1(A* p){
p->name();
}
void outCall2(A p){
p.name();
}
main函数里验证
A* p1 = new B1();
A& p2 = *(new B1());
A p3 = *(new B1());
p1->name();//调用B1的name()
p2.name();//调用B1的name()
p3.name();//调用A的name()
A* p1 = new B1();
A& p2 = *(new B1());
A p3 = *(new B1());
p1->name();//调用B1的name()
p2.name();//调用B1的name()
p3.name();//调用A的name()
outCall1(p1);
outCall1(p2);
outCall2(p2);//调用A的name()
析构函数的多态性;
我们在A,B1,B1_1分别加入析构函数
~A(){
cout<<"destroy A"<
然后执行像以下代码
A* p1 = new B1();
A* p1_1 = new B1_1();
delete p1;
delete p1_1;
我们会发现输出只能调用到A的析构函数
destroy A
然后我们在~A()前加上virtual使其成为虚函数。
然后再次编译得到
destroy B1
destroy A
destroy B1_1
destroy A
于是我们在声明A*实例化却是子函数的情况下也做到了同时调用了父类和子类的析构函数
多继承,注意什么情况需要虚继承;
下面我们来考虑一种特殊情况—环形继承
图中A,B,C,D分别对应我们的A,B1,B1_1,E;
我们现在可以简化代码
class A
{
public:
void name() {
cout << "i am A" << endl;
}
};
class B1 :public A{
}
class B1_1:public A{
}
class E:public B1, public B1_1{
}
然后我们
A* p = new E(); //这里你会发现报错了
p->name();
E同时继承B1 and B1_1,于是他有两个A的name,于是就报错了,那要怎么解决呢?于是我们引进了虚继承
class B1 :virtual public A{
}
class B1_1:virtual public A{
}
然后E就会只要B1中A的name()因为class E:public B1, public B1_1这里B1在前
但同时我们发现另一个问题,那就是这里我们不能在B1和B1_1里写name(),当然你不能有两个声明完全一样的函数。
结语
经过了自己编写的这一堆基本的c++继承和多态的操作,我对c++越加熟悉,其中的虚继承印象尤为深刻。
怎么解决呢?于是我们引进了虚继承
[外链图片转存中…(img-1KLIOMF5-1635770709970)]
class B1 :virtual public A{
}
class B1_1:virtual public A{
}
然后E就会只要B1中A的name()因为class E:public B1, public B1_1这里B1在前
但同时我们发现另一个问题,那就是这里我们不能在B1和B1_1里写name(),当然你不能有两个声明完全一样的函数。
结语
经过了自己编写的这一堆基本的c++继承和多态的操作,我对c++越加熟悉,其中的虚继承印象尤为深刻。



