C++的继承使用方法

类模板的继承:

子类会继承父类的所有属性,

注意:被继承的父类必须要有无参构造函数

调用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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值