基类与派生类的关系(C++)

2023-12-29 22:36:54

3.2 基类与派生类的关系

3.2.1 向上造型和向下造型

子类对象会继承基类的属性的行为,任何时候子类对象都可以被当做基类类型的对象,通过子类对象可以直接访问基类中的成员,如同是基类对象在访问它们一样

**向上造型(upcast):**将子类类型的指针或引用转换为基类类型的指针或引用;这种操作性缩小的类型转换,在编译器看来是安全的,可以隐式转换。

**向下造型(downcast):**将基类类型的指针或引用转换为子类类型的指针或引用;这种操作性放大的类型转换,在编译器看来是危险的,不能隐式转换,但是可以显式转换。

#include <iostream>
using namespace std;

class Human{
private:
	int m_private;
protected:
	string m_name;
	int m_age;
public:
	Human(const string& name, int age){
		m_name = name;
		m_age = age;
	}
	void eat(const string& food){
		cout << "今天吃:" << food << endl;
	}
	void sleep(int hour){
		cout << "今天睡了: " << hour << "小时" << endl;
	}
};

class Student : public Human{
private:
	int m_no;
public:
	Student(const string& name, int age, int no):Human(name, age), m_no(no){
		// Human(name,age);//error
	}
	void who() {
		cout << "我是:" << m_name << " 今年: " << m_age << " 学号:" << m_no << endl;
	}
	void learn(const string& course){
		cout << "我正在学习:" << course << endl;
	}
};

class Teacher : public Human{
private:
	int m_salary;
public:
	Teacher(const string& name, int age, int salary):Human(name, age), m_salary(salary){
	}
	void who(){
		cout << "我是:" << m_name << " 今年:" << m_age << " 工资是: " << m_salary << endl;
	}
	void teach(const string& course) {
		cout << "我正在讲: " << course << endl;
	}
};
int main(void) {

	Human hu("王铁蛋", 18);
	hu.eat("炸鸡柳");
	hu.sleep(18);

	Student st("刘钢蛋", 19, 10002);
	st.who();
	st.eat("汉堡包");
	st.sleep(19);
	st.learn("C++编程");

	Teacher te("王翠花", 32, 15000);
	te.who();
	te.teach("C++");

	// Student * --------->  Human * : 向下造型
	Human *ph = &st; 
	ph->eat("汉堡包");
	ph->sleep(19);
	//ph->who(); //error  Human基类中没有who()函数 
	
	// Human * -----------> Student * : 向上造型 (合理)
	//Student *s1 = &hu;//error
	Student *s1 = static_cast<Student *>(ph); 
	s1->who();

	Human h("赵四", 39);
	// Human * --------> Student * : 向上造型(不合理)
	Student *s2 = static_cast<Student *>(&h);
	s2->who();// 扩大访问范围了  输出的结果不确定
	return 0;
}

3.2.2 成员函数的重定义(名字隐藏)

重定义:简单的说就是子类中定义了和父类的同名函数,对父类的成员函数造成了隐藏(多态时会进一步限定)

#include <iostream>
using namespace std;

class Base{
private:
	int m_x;
public:
	void set(int x) {
		m_x = x;
	}
	void print(){
		cout << "Base class: " << "m_x = " << m_x << endl;
	}
};

class Derived: public Base {
private:
	int m_y, m_z;
public:
	void set(int y, int z) {
		m_y = y;
		m_z = z;
	}
	void print(){
		cout << "Derived class: " << "m_y = " << m_y << "m_z = " << m_z << endl;
	}
};

int main(void) {

	Derived d;
	d.Base::set(10);
	d.set(10,20);	//这个地方默认是 派生类中的成员函数
	d.Base::print();//想要搞清楚调用基类还是派生类中的成员函数 加作用域限定符
	d.print();

	return 0;
}

文章来源:https://blog.csdn.net/qq_36091214/article/details/135298712
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。