类模板的继承:
子类会继承父类的所有属性,
注意:被继承的父类必须要有无参构造函数
调用Test2之前要先调用Test1的无参构造函数
#include<iostream>
using namespace std;
template <class T>
class Test1
{
public:
T t1;
//无参构造函数
Test1() { cout << "子类无参构造函数" << endl; }
//有参构造函数
Test1(T t11)
{
t1 = t11;
}
void print() { cout << t1 << endl; }
};
template <class T1>
class Test2 :public Test1<string>//把T声明为字符串,也可以写成抽象类型
{
public:
T1 t;
Test2(T1 tt)
{
t = tt;
}
void display() { cout << t << endl; }
};
int main()
{
Test2<int> b(123);
b.display();
b.t1 = "string";
b.print();
return 0;
}
公有继承练习题:
定义人类,再用老师类学生类继承人类
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
char name[20];
};
class Student :public Person
{
public:
};
class Teacher:public Person
{
public:
};
int main()
{
Student one;
strcpy(one.name, "周");
cout << one.name << endl;
Teacher two;
strcpy(two.name, "刘");
cout << two.name << endl;
return 0;
}
练习题:
定义人类,他有一个成员函数“SayHllo()输出:我是人类,再定义一个教师类,也有一个SayHello()函数输出:我是老师
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
void SayHello()
{
cout << "我是人类" << endl;
}
};
class Teacher:public Person
{
public:
void SayHello()
{
cout << "我是老师" << endl;
}
};
int main()
{
Person you;
Teacher me;
you.SayHello();
me.SayHello();//继承会覆盖父类的同名成员函数
you.Person::SayHello();//用子类来调用父类同名成员函数的使用形式
return 0;
}
多重继承的声明方法:
代码:
#include<iostream>
#define _CTR_SECURE_NO _WARNINGS
using namespace std;
//鸟类
class CBird
{
public:
void fly() { cout << "I can fly" << endl; }
void breath() { cout << "I can breath" << endl; }
};
//鱼类
class CFish
{
public:
void swim() { cout << "I can swimming" << endl; }
void breath() { cout << "I can breath" << endl; }
};
class WaterBird:public CBird,public CFish { public:};
int main()
{
WaterBird me;
me.CBird::breath();//两个父类都有一定要指定他继承于哪一个要不然会产生二义性
me.fly();
me.swim();
return 0;
}
继承中的函数隐藏(成员函数)覆盖
定义一个Vehicle类,作为基类,该类中定义一个move()方法,然后定义Train和Car类都继承子Vehicle类,输出“交通工具都可以移动” “ 火车在铁轨上行驶” “骑车在公路上行驶”
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Vehicle
{
public:
void move()
{
cout << "交通工具都可以移动" << endl;
}
};
class Train:public Vehicle
{
public:
void move()
{
cout << "火车在铁轨上行驶" << endl;
}
};
class Car :public Vehicle
{
public:
void move()
{
cout << "汽车在公路上行驶" << endl;
}
};
int main()
{
Vehicle one;
one.move();
Train two;
two.move();
Car three;
three.move();
three.Vehicle::move();//通过子类访问父类成员函数
return 0;
}
虚继承:
虚拟继承是多重继承中的菱形继承所特有的概念。虚拟基类是为解决多重继承而出现的。主要是为了解决产生的数据冗余问题。就是使派生类只保留一份基类的属性或者数据。
看一下这个代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class A
{
public:
int age;
A() { cout << "A的构造函数" << endl; }
};
class B :virtual public A
{
};
class C :virtual public A
{
};
class D :public B, public C
{
public:
void set(int a)
{
age = a;
}
//若不加virtual关键字则会出现指定不明确的现象
//因为B和C都继承了A一共会有三个age加一个virtual就表明它继承的是A里面的age
};
int main()
{
D one;
one.set(3);
cout << one.age << endl;
return 0;
}
运行结果:
虚继承例题:
定义动物类,定义鸟类和哺乳类,他们继承动物类,定义鸭嘴兽类,继承前两个类,验证鸭嘴兽类存在两个动物类的副本,如果存在通过虚函数改正这个问题。
#include<iostream>
using namespace std;
class Animal
{
public:
int age;
};
class Bird:public Animal
{
};
class Mammal :public Animal
{
};
class Ysz :public Bird, public Mammal
{
};
int main()
{
Ysz one;
//不能直接写成:one.age = 19;因为不明确
one.Bird::age = 19;
cout << "age=" << one.Bird::age << endl;
//或者直接使用虚继承在两个公有继承的前面加一个virtual关键字即可直接使用age
return 0;
}
继承中的访问问题:
#include<iostream>
using namespace std;
class MM
{
public:
MM(string name,int age):name(name),age(age){}
void print()
{
cout << "girl" << endl;
}
protected:
string name;
int age;
};
class Boy :public MM
{
public:
//赋值遵循就近原则
Boy(string name,int age,string mmName,int mmAge):name(name),age(age),MM(mmName,mmAge){}
void print()
{
//就近原则,在子类中优先使用自己的属性
cout << "name= " << name << " age=" << age << endl;
//作用域类名限定
cout << "类名限定" << "name= " << MM::name << " age=" << MM::age << endl;
}
protected:
string name;
int age;
};
int main()
{
Boy coolBoy("男孩", 20, "女孩", 19);
cout << "I Love You" << endl;
coolBoy.print();
cout << endl;
cout << "主函数里使用类名作用域限定输出结果:" << endl;
coolBoy.MM::print();//类名作用域限定
//指针访问也是就近原则在没有virtual的情况下
cout << "指针访问" << endl;
Boy* pBoy = new Boy("boy", 20, "girl", 18);
pBoy->print();
delete pBoy;
cout << endl;
cout << "父类指针被子类对象初始化的调用情况(一般情况下不存在相反的情况)" << endl;
MM* pMM = new Boy("MBoy", 21, "mm", 19);
pMM->print();
cout << "在没有virtual时调用对象看类型,不看对象,有virtual时则相反" << endl;
return 0;
}
结果:
#include<iostream>
using namespace std;
class Base1 {
public:
virtual void display()
{
cout << "Base1::display()" << endl;
}
};
class Base2 :public Base1
{
public:
void display()
{
cout << "Base2::display()" << endl;
}
};
class Derived :public Base2
{
public:
void display()
{
cout << "Derive::display()" << endl;
}
};
void fun(Base1* ptr)
{
ptr->display();
}
int main()
{
Base1 base1;
Base2 base2;
Derived derived;
fun(&base1);
fun(&base2);
fun(&derived);
return 0;
}
#include<iostream>
#include<string>
using namespace std;
class Base1 {
public:
virtual void display()
{
cout << "Base1::display()" << endl;
}
};
class Base2 :public Base1
{
public:
void display()
{
cout << "Base2::display()" << endl;
}
};
class Derived :public Base2
{
public:
void display()
{
cout << "Derive::display()" << endl;
}
};
void fun(Base1* ptr)
{
ptr->display();
}
int main()
{
Base1 base1;
Base2 base2;
Derived derived;
fun(&base1);
fun(&base2);
fun(&derived);
return 0;
}
由上面的例子我们可以看出:
通过基类类型的指针可以访问到正在指向的对象的成员,这样就能实现对同一类族中的对象进行统一处理,抽象度更高,程序更间接、更高效
2021/6/23