C++---继承

本文详细介绍了C++中的继承概念,包括公有、私有和保护继承方式,以及它们的特点和使用场景。通过实例展示了如何在类间复用代码,处理多继承和菱形继承的问题,以及一个综合案例,涉及图形类Shape及其派生类Circle和Square的定义和操作。
摘要由CSDN通过智能技术生成

继承的概念及入门案例

在C++中,继承是一种面向对象编程的重要概念,他允许一个类(成为派生类)继承另一个类(成为基类)的特性和行为

class B:继承方式A{
    

};

        其中A成为父类(基类、超类)        B类成为子类(派生类)

继承方式:

       公有继承(public inheritance)        私有继承(private inheritance)        保护继(protected inheritance)

继承的特点

        通过继承,派生类可以获得基类的成员变量和成员函数,并且可以添加新成员变量和成员函数。这样可以实现代码的复用

案例

#include<iostream>
#include<string>
using namespace std;

class Animal {
public:
	//属性
	string name;
	int age;
	//行为
	void eat() {
		cout << "在吃饭" << endl;
	}
	void sleep() {
		cout << "在睡觉" << endl;
	}
};

class Dog :public Animal {
public:
	//属性
	string color;
	//行为
	void lookhome() {
		cout << name << "在看家" << endl;
	}
	void eat() {
		cout << name << "在吃骨头" << endl;
	}//继承的扩展
	void sleep() {
		cout << name << "在狗窝里睡觉" << endl;
	}//继承的扩展
};//子类
class Cat :public Animal {
public:
	string breed;
	void catchMouse() {
		cout << name << "在抓老鼠" << endl;
	}
	void eat() {
		cout << name << "在吃老鼠" << endl;
	}//继承的扩展
	void sleep() {
		cout << name << "在猫爬架上睡觉" << endl;
	}//继承的扩展
};
int main() {
	//创建Dog对象
	Dog dog;
	dog.name = "旺财";
	dog.age = 1;
	dog.color = "黄色";
	dog.eat();
	dog.sleep();
	dog.lookhome();

	//创建Cat对象
	Cat cat;
	cat.name = "大福";
	cat.age = 5;
	cat.breed = "银渐层";
	cat.eat();
	cat.sleep();
	cat.catchMouse();

	return 0;
}

继承的好处       

        1.代码复用:

                避免了重复编写相同的代码,提高了代码的复用性;

        2.扩展性

                可以在已有类的基础上进行扩展和修改,添加新的功能或修改现有功能,使代码更具灵活性和可扩展性。

继承使用场景

        当多个类之间有相同的属性和方法时,可以将这些共同部分抽取出来放在一个基类中,然后其他类通过继承基类来复用这些代码。

继承方式

什么是权限修饰符?

                用来限制类中的成员(成员变量、成员方法....)能够被访问的范围。

修饰符本类里子孙类外部类
public
protected
private

继承方式--公有继承(全部)

#include<iostream>
#include<string>
using namespace std;

class Father {
public:
	int a;
protected:
	int b;
private:
	int c;

public:
	void fun1() {
		cout << "父类的公共方法" << endl;
	}
protected:
	void fun2() {
		cout << "父类的保护方法" << endl;
	}
private:
	void fun3() {
		cout << "父类的私人方法" << endl;
	}
};

//公共继承 
class Son1 :public Father {
public:
	void fun() {
		a = 10;//public
		b = 20;//protected
		//c = 30;//报错,父类私有,子类不能继承

		fun1();//public
		fun2();//protected
		//fun3();//报错,父类私有,子类不能继承
	}
};
int main() {
	Son1 s1;
	//父类中的a是public,子类可以使用,其他类也可以使用
	s1.a = 10;
	//父类中的a是protected,子类不可以使用,其他类不可以使用
	//s1.b = 20;
	//父类中的a是private,子类不可以使用,其他类不可以使用
	//s1.c = 30;
	s1.fun();

	return 0;
}

继承方式--保护继承(本类和子类)

class Son2:protected Father{
public:
	void fun() {
		a = 10;
		b = 20;
		//c = 30;报错,父类私有子类不能访问
		fun1();//protected权限降级
		fun2();//protected
		//fun3();报错,父类私有子类不能访问
	}
}

其中a在子类中降级为protected

继承方式--私有继承(本类和子类)

class Son3:private Father{
public:
	void fun() {
		a = 10;//private,权限降级
		b = 20;//private,权限降级
		c = 30;报错,父类私有子类不能访问
		fun1();//private,权限降级
		fun2();//private,权限降级
		fun3();报错,父类私有子类不能访问
	}
}

注意:在类中的有私有变量时,返回值大小为12,反之为8。

通过返回值的字节大小,可以判断出父类中私有成员也是被子类继承,只是由编译器给隐藏后访问不到。

继承中的变量与函数

继承中的构造和析构顺序

        父类构造函数-子类构造函数-子类析构函数-父类析构函数

继承同名成员处理方式

                访问子类同名成员 直接访问即可

                访问父类 同名成员 需要加作用域

class Base{
public:
    int m_A;

public:
    Base(){
        m_A=100;
    }
    void fun(){
        cout<<"Base--fun()调用"<<endl;
    }
    void fun(int a){
        cout<<"Base--fun(int a)调用"<<endl;
    }
};
class Son:public Base{
public:
    int m_A;
public:
    Son(){
        m_A=200;
    }
    void fun(){
        cout<<"Son--fun()调用"<<endl;
    }
    void fun(int a){
        cout<<"Son--fun(int a)调用"<<endl;
    }    
};
        
int main(){
    //创建对象
    Son son;

    //访问子类成员:直接访问
    cout<<son.m_A<<endl;
    son.fun();
    son.fun(10);

    //访问父类成员:添加父类作用域
    cout<<son.Base::m_A<<endl;
    son..Base::fun();
    son..Base::fun(10);

}

总结:

        1.子类对象可以直接访问到子类中同名成员

        2.子类对象加作用域可以访问到父类同名成员

继承同名静态成员处理方式

                访问子类同名成员 直接访问即可

                访问父类 同名成员 需要加作用域

多继承与菱形继承

多继承语法

        C++允许一个类继承多个类

#include<iostream>
#include<string>
using namespace std;

class Base1 {
public:
	int m_A;

	Base1() {
		m_A = 100;
	}
};
class Base2 {
public:
	int m_B = 200;
	
	Base2() {
		m_B = 200;
	}
};
class Son :public Base1, public Base2 {//多继承
public:
	int m_C;
	int m_D;
public:
	Son() {
		m_C = 300;
		m_D = 400;
	}
};


//访问
int main() {
	Son son;
	cout << "sizeof Son:" << sizeof(son) << endl;
    //多继承容易产生成员同名的情况
    //通过使用类名作用域可以区分调用哪一个基类成员
	cout << son.Base1::m_A << endl;//100
    cout << son.Base2::m_A << endl;//200
	cout << son.m_B << endl;//200
	cout << son.m_C << endl;//300
	cout << son.m_D << endl;//400
}

注意:多继承中如果父类中出现了同名情况,子类使用时要加作用域。

菱形继承(钻石继承)

概念:

        1.两个派生类继承同一个基类

        2.又有某个类同时继承着两个派生类

#include<iostream>
#include<string>
using namespace std;

class Animal {
public:
	int m_Age;
};

//继承前加virtual关键字后,变为虚继承
//此时公共的父类Anmial成为虚基类
class Sheep :virtual public Animal {};
class Tuo : virtual public Animal {};
class SheepTuo :public Sheep, public Tuo {};

int main() {
	SheepTuo st;
	//st.m_Age = 18;//报错不明确
	//使用作用域
	st.Sheep::m_Age = 28;
	st.Tuo::m_Age = 28;
	cout << "st.Sheep::m_Age=" << st.Sheep::m_Age << endl;
	cout << "st.Tuo::m_Age=" << st.Tuo::m_Age << endl;
	cout << "st.m_Age= " << st.m_Age << endl;

}
//
//输出:
//	st.Sheep::m_Age =28
//	st.Tuo::m_Age =28
//	st.m_Age =28

总结:

        菱形继承带来的主要问题是子类继承两份相同数据,导致资源浪费及毫无意义

        利用虚继承可以菱形继承问题

综合案例

要求:1.编写图形类Shape,有方法draw()画出图形、函数area()计算面积

2.编写具体图形类:圆Circle,正方形Square,均继承自父类Shape分别实现自己的draw()和area(),输出有意义的描述信息。

#include<iostream>
#include<string>
using namespace std;

class Shape{
public:
	void draw() {
		cout << "Shape drawing ..." << endl;
	}
	double area(int i) {
		return 0;
	}
};

class Circle:public Shape {
private:
	double radium;
	double const PI = 3.14;
public:
	Circle(double r) {
		radium = r;
	}
	void draw() {
		cout << "Circle drawing..." << endl;
	}
	double area() {
		return PI * radium * radium;
	}
};

class Square :public Shape {
private:
	double side;
public:
	Square(double side) {
		this->side = side;
	}
	void draw() {
		cout << "Square drawing..." << endl;
	}
	double area() {
		return side * side;
	}
};
int main() {
	Shape s;
	s.draw();
	cout << "Shape's area:" << s.area()<< endl;
	Circle c(10.0);//有参构造函数
	c.draw();
	cout << "Circle'area:" << c.area() << endl;
	Square sq(20.0);//有参构造函数
	sq.draw();
	cout << "Square's area:" << sq.area() << endl;
	return 0;
}

  • 45
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值