一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止。具体表现在:
- 派生类的对象可以被赋值给基类对象。
- 派生类的对象可以初始化基类的引用。
- 指向基类的指针也可以指向派生类。
通过基类对象名、指针只能使用从基类继承的成员
举例:
1.派生类的对象可以被赋值给基类对象。这是一个总纲领,意味着在需要基类对象的地方,我们都可以用一个派生类对象来替代。
这会导致对象切片
#include <iostream>
#include <string>
// 基类
class person {
public:
std::string name;
void introduce() {
std::cout << "我是一个人, 我的名字是 " << name << std::endl;
}
};
// 公有派生类
class student : public person {
public:
int studentid; // 派生类特有的成员
void study() { // 派生类特有的方法
std::cout << name << " 正在学习, 学号是 " << studentid << std::endl;
}
};
int main() {
student stu;
stu.name = "张三";
stu.studentid = 101;
person per;
per = stu; // 将派生类对象 stu 赋值给 基类对象 per
std::cout << "基类对象 per 的名字: " << per.name << std::endl;
per.introduce();
// per.studentid = 102; // 错误! per 是一个 person 对象, 它没有 studentid 成员。
// per.study(); // 错误! per 是一个 person 对象, 它没有 study() 方法。
}解释:
当执行 per = stu; 时,stu 对象中从 person 继承来的部分(也就是 name 成员)被拷贝到了 per 对象中。stu 对象自己独有的成员(studentid)被完全“切掉”和丢弃了。因此,per 仍然是一个纯粹的 person 对象,它只知道 name,不知道任何关于 studentid 或 study() 的信息。
2.派生类的对象可以初始化基类的引用。这是实现多态的一种非常安全和常见的方式,不会发生对象切片。
#include <iostream>
#include <string>
// 基类
class person {
public:
std::string name;
void introduce() {
std::cout << "我是一个人, 我的名字是 " << name << std::endl;
}
};
// 公有派生类
class student : public person {
public:
int studentid; // 派生类特有的成员
void study() { // 派生类特有的方法
std::cout << name << " 正在学习, 学号是 " << studentid << std::endl;
}
};
int main() {
student stu;
stu.name = "李四";
stu.studentid = 102;
// 使用派生类对象 stu 来初始化一个基类的引用
person& per_ref = stu;
std::cout << "通过基类引用访问名字: " << per_ref.name << std::endl;
per_ref.introduce(); // 调用的是 person 的方法
// per_ref.study(); // 错误! 虽然引用指向的是 student 对象,但引用本身是 person 类型,
// 只能访问 person 中定义的成员。
}解释:
per_ref 是基类 person 的一个引用,它直接绑定到了 stu 这个派生类对象上。内存中只有一个 stu 对象,没有发生任何拷贝。per_ref 成为了 stu 对象的一个“别名”,但这个别名是 person 类型的,所以它有一个受限的“视野”。
3.指向基类的指针也可以指向派生类。这是实现多态最核心、最灵活的方式,同样不会发生对象切片。
#include <iostream>
#include <string>
// 基类
class person {
public:
std::string name;
void introduce() {
std::cout << "我是一个人, 我的名字是 " << name << std::endl;
}
};
// 公有派生类
class student : public person {
public:
int studentid; // 派生类特有的成员
void study() { // 派生类特有的方法
std::cout << name << " 正在学习, 学号是 " << studentid << std::endl;
}
};
int main() {
student stu;
stu.name = "王五";
stu.studentid = 103;
// 基类指针指向派生类对象
person* per_ptr = &stu;
std::cout << "通过基类指针访问名字: " << per_ptr->name << std::endl;
per_ptr->introduce(); // 调用的是 person 的方法
// per_ptr->study(); // 错误! 指针类型是 person*,它“看”不到 student 类中新增的成员。
}解释:
`per_ptr` 是一个 `person` 类型的指针,它存储了 `stu` 对象的内存地址。和引用一样,它也只是提供了一个基类“视角”来观察这个派生类对象。
到此这篇关于详解c++类型兼容性规则的文章就介绍到这了,更多相关c++类型兼容性规则内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论