1、继承类的实现 定义一个基类Animal,包含姓名、年龄等成员变量和成员函数。 创建一个派生类Dog,继承自Animal类,并添加新的成员变量和成员函数。 尝试使用公有继承、私有继承和保护继承,观察继承方式对成员访问权限的影响。 2、类型兼容练习 创建Animal和Dog类的对象,并尝试将Dog对象赋值给Animal类型的指针或引用。 通过指针或引用调用对象的成员函数,验证类型兼容的效果。 3、派生类构造函数与析构函数 为Dog类实现构造函数和析构函数,确保在创建和销毁对象时能够正确初始化和释放资源。 观察派生类构造函数调用基类构造函数的顺序和方式。 观察派生类析构函数调用基类析构函数的顺序和方式。 4、在派生类隐藏基类成员函数 在Dog类中定义一个与Animal类中同名的成员函数。 调用Dog对象的该函数,观察基类成员函数的隐藏现象。 尝试使用作用域解析运算符::来访问被隐藏的基类成员函数。 5、多继承方式 定义一个基类Flying,表示飞行能力。 创建一个派生类Bat,同时继承自Animal和Flying类。 在Bat类中添加新的成员变量和成员函数,实现蝙蝠的特有功能。 创建Bat类的对象,并测试其继承自Animal和Flying的功能。 6、继承派生类构造函数与析构函数 为Bat类实现构造函数和析构函数,确保能够正确初始化所有基类和派生类的成员变量。 观察多继承时构造函数和析构函数的调用顺序。 7、多继承的二义性问题 在Animal和Flying类中定义一个同名的成员函数。 在Bat类中尝试调用该成员函数,观察二义性问题的出现。 使用作用域解析运算符::来明确指定要调用的基类成员函数,解决二义性问题。 8、虚继承 修改Bat类的继承方式,使用虚继承来继承Animal和Flying类。 观察虚继承对构造函数和析构函数的影响。 分析虚继承在解决多继承二义性问题中的作用和优势。
1. 继承类的实现
首先,定义一个基类Animal
,它包含姓名和年龄等成员变量,以及一些成员函数。然后创建一个派生类Dog
,继承自Animal
类,并添加新的成员变量和成员函数。以下是使用不同继承方式的示例:
公有继承
在公有继承中,基类的公有成员和保护成员在派生类中保持原有的访问属性。派生类的新增成员可以访问基类的公有成员和保护成员,但访问不了基类的私有成员。派生类的对象只能访问派生类的公有成员(包括继承的公有成员),访问不了保护成员和私有成员12378。
class Animal {
public:
string name;
int age;
void speak() {
cout << "Animal speaks" << endl;
}
};
class Dog : public Animal {
public:
void bark() {
cout << "Dog barks" << endl;
}
};
私有继承
在私有继承中,基类的公有成员和保护成员都作为派生类的私有成员。派生类中的成员函数可以直接访问这些成员,但是通过派生类的对象不能直接访问从基类继承的任何成员24。
class Dog : private Animal {
// Dog 类的实现,继承了 Animal 的私有成员
};
保护继承
在保护继承中,基类的所有公有成员和保护成员都成为派生类的保护成员。这些成员只能被派生类的成员函数或友元访问,基类的私有成员仍然是私有的28。
class Dog : protected Animal {
// Dog 类的实现,继承了 Animal 的保护成员
};
2. 类型兼容练习
创建Animal
和Dog
类的对象,并尝试将Dog
对象赋值给Animal
类型的指针或引用。通过指针或引用调用对象的成员函数,可以验证类型兼容的效果。
Animal* animalPtr = new Dog();
animalPtr->speak(); // 调用 Animal 类的 speak 函数
3. 派生类构造函数与析构函数
为Dog
类实现构造函数和析构函数,确保在创建和销毁对象时能够正确初始化和释放资源。观察派生类构造函数调用基类构造函数的顺序和方式,以及派生类析构函数调用基类析构函数的顺序和方式。
class Dog : public Animal {
public:
Dog() {
// 初始化 Dog 类的成员
}
~Dog() {
// 析构 Dog 类的资源
}
};
4. 在派生类隐藏基类成员函数
在Dog
类中定义一个与Animal
类中同名的成员函数。调用Dog
对象的该函数,可以观察到基类成员函数的隐藏现象。尝试使用作用域解析运算符::
来访问被隐藏的基类成员函数。
class Dog : public Animal {
public:
void speak() {
cout << "Dog speaks" << endl;
}
};
Dog myDog;
myDog.speak(); // 调用 Dog 类的 speak 函数
myDog.Animal::speak(); // 使用作用域解析运算符调用 Animal 类的 speak 函数
5. 多继承方式
定义一个基类Flying
,表示飞行能力。创建一个派生类Bat
,同时继承自Animal
和Flying
类。在Bat
类中添加新的成员变量和成员函数,实现蝙蝠的特有功能。
class Flying {
public:
void fly() {
cout << "Flying" << endl;
}
};
class Bat : public Animal, public Flying {
public:
void echolocate() {
cout << "Echolocating" << endl;
}
};
6. 继承派生类构造函数与析构函数
为Bat
类实现构造函数和析构函数,确保能够正确初始化所有基类和派生类的成员变量。观察多继承时构造函数和析构函数的调用顺序。
class Bat : public Animal, public Flying {
public:
Bat() : Animal(), Flying() {
// 初始化 Bat 类的成员
}
~Bat() {
// 析构 Bat 类的资源
}
};