当前位置: 首页 > news >正文

网站美工设计收费高端网站建设公司哪家公司好

网站美工设计收费,高端网站建设公司哪家公司好,wordpress分类目录修改,企业产品营销策划推广文章目录 C 继承详解#xff1a;初阶理解与实战应用前言第一章#xff1a;继承的基本概念与定义1.1 继承的概念1.2 继承的定义 第二章#xff1a;继承中的访问权限2.1 基类成员在派生类中的访问权限2.2 基类与派生类对象的赋值转换2.2.1 派生类对象赋值给基类对象2.2.2 基类… 文章目录 C 继承详解初阶理解与实战应用前言第一章继承的基本概念与定义1.1 继承的概念1.2 继承的定义 第二章继承中的访问权限2.1 基类成员在派生类中的访问权限2.2 基类与派生类对象的赋值转换2.2.1 派生类对象赋值给基类对象2.2.2 基类指针和引用的转换2.2.3 强制类型转换的使用 第三章继承中的作用域与成员访问3.1 作用域的独立性与同名成员的隐藏3.1.1 函数的隐藏 3.2 派生类的默认成员函数3.2.1 构造函数的调用顺序3.2.2 拷贝构造函数与赋值运算符的调用3.2.3 析构函数的调用顺序3.2.4 虚析构函数 总结 C 继承详解初阶理解与实战应用 欢迎讨论在学习过程中如果有任何疑问或想法欢迎在评论区留言一起讨论。 点赞、收藏与分享觉得这篇文章对你有帮助吗记得点赞、收藏并分享给更多的朋友吧你们的支持是我不断进步的动力 分享给更多人如果你觉得这篇文章对你有帮助欢迎分享给更多对 C 感兴趣的朋友一起学习进步 前言 C 继承机制是面向对象编程的重要组成部分能够帮助开发者实现代码的复用和扩展。通过继承开发者可以基于已有的类创建新的类从而避免重复代码编写提升开发效率。然而继承的使用并不总是那么简单特别是在涉及到复杂继承关系时容易导致一些新手难以理解的困惑。本篇文章将通过细致入微的分析帮助大家从初阶的角度理解 C 中继承的基本原理并结合实际的代码示例逐步深入剖析继承中的难点和注意事项。 第一章继承的基本概念与定义 1.1 继承的概念 在C中继承Inheritance 是面向对象程序设计中的一种机制它允许程序员在已有类即基类或父类的基础上扩展或修改功能从而形成新的类即派生类或子类。这种机制能够复用已有的代码并且通过层次化的类结构展示了面向对象编程由简单到复杂的认知过程。 举个例子假设有一个基类 Person定义了基本的个人信息如姓名和年龄。现在需要创建一个 Student 类除了拥有基本的个人信息外还需要增加学号。通过继承Student 类可以复用 Person 类中的代码而不必重新编写这些属性。 class Person { public:void Print() {cout name: _name endl;cout age: _age endl;}protected:string _name peter; // 姓名int _age 18; // 年龄 };// Student类继承自Person类 class Student : public Person { protected:int _stuid; // 学号 };在以上代码中Student 类继承了 Person 类的成员函数和成员变量这意味着 Student 类中包含了 _name 和 _age 两个属性以及 Print() 函数。通过继承我们实现了代码的复用。 1.2 继承的定义 继承在 C 中的定义主要通过以下格式实现 class 子类名 : 继承方式 基类名 {// 子类的成员 };其中继承方式 可以是 public、protected 或 private它们决定了基类的成员在派生类中的访问权限。 public 继承基类的 public 成员在派生类中保持 publicprotected 成员保持 protected。protected 继承基类的 public 成员在派生类中变为 protectedprotected 成员保持 protected。private 继承基类的 public 和 protected 成员在派生类中均变为 private。 示例代码 class Teacher : public Person { protected:int _jobid; // 工号 };int main() {Student s;Teacher t;s.Print();t.Print();return 0; }在这个示例中Student 和 Teacher 都继承了 Person 类的 Print() 函数通过 s.Print() 和 t.Print() 可以分别输出 Student 和 Teacher 对象的姓名和年龄。 第二章继承中的访问权限 2.1 基类成员在派生类中的访问权限 基类的 public、protected 和 private 成员在派生类中的访问权限取决于继承方式。下面是不同继承方式下的访问权限表 类成员public 继承protected 继承private 继承基类的 public 成员publicprotectedprivate基类的 protected 成员protectedprotectedprivate基类的 private 成员不可见不可见不可见 从表中可以看出基类的 private 成员在派生类中始终不可见不可访问无论采用何种继承方式。然而基类的 protected 成员和 public 成员则根据继承方式在派生类中具有不同的访问级别。 注意如果需要基类的某个成员在派生类中可访问但不希望类外部访问则可以将其设置为 protected这样可以更好地控制访问权限。 2.2 基类与派生类对象的赋值转换 在C中基类和派生类对象的赋值转换是一个比较常见的操作场景。通常情况下派生类对象可以赋值给基类对象或者通过基类的指针或引用来操作派生类对象。这种转换机制使得C在继承结构中实现了多态和代码复用。但需要注意的是基类对象不能直接赋值给派生类对象。 2.2.1 派生类对象赋值给基类对象 派生类对象包含了基类的成员因此派生类对象赋值给基类对象时实际上是将派生类中属于基类的那一部分赋值给基类对象。这种操作称为切片Slicing即派生类对象中的基类部分被切割下来赋值给基类对象。 示例代码如下 class Person { public:string _name; protected:int _age; };class Student : public Person { public:int _stuid; };int main() {Student s;s._name John;s._stuid 1001;Person p s; // 切片操作将派生类对象赋值给基类对象cout Name: p._name endl; // 输出 John// cout p._stuid; // 错误基类对象无法访问派生类的成员return 0; }在上面的代码中Student 对象 s 被赋值给 Person 对象 p。但是由于 Person 类没有 stuid 成员p 无法访问 Student 类中的 _stuid 成员。因此这里发生了切片操作p 只保留了 Student 类中 Person 类的那部分内容。 2.2.2 基类指针和引用的转换 派生类对象可以赋值给基类的指针或引用这是实现多态的重要前提条件。通过基类指针或引用程序可以在运行时动态绑定到派生类的成员函数。这种方式允许我们在不需要修改代码的情况下扩展程序的功能。 class Person { public:virtual void Print() {cout Person: _name endl;} protected:string _name Alice; };class Student : public Person { public:void Print() override {cout Student: _name , ID: _stuid endl;} private:int _stuid 123; };void PrintPersonInfo(Person p) {p.Print(); // 基类引用调用虚函数实现多态 }int main() {Student s;PrintPersonInfo(s); // 输出 Student: Alice, ID: 123return 0; }在这个例子中我们通过基类 Person 的引用调用 Student 类中的 Print() 函数实现了运行时多态。派生类对象 s 被传递给基类引用 p并正确调用了 Student 类的重写函数 Print()。 2.2.3 强制类型转换的使用 在某些特殊情况下基类指针或引用可能需要转换为派生类的指针或引用。C 提供了 dynamic_cast、static_cast 等多种类型转换方式。在继承关系中使用 dynamic_cast 进行安全的类型转换尤为重要特别是在处理多态时。 Person* pp new Student(); // 基类指针指向派生类对象 Student* sp dynamic_castStudent*(pp); // 安全的向下转换 if (sp) {sp-Print(); } else {cout Type conversion failed! endl; }dynamic_cast 在运行时进行类型检查确保转换是安全的。如果转换失败将返回 nullptr从而避免越界访问的风险。 第三章继承中的作用域与成员访问 3.1 作用域的独立性与同名成员的隐藏 在继承关系中基类与派生类各自拥有独立的作用域。如果派生类中定义了与基类成员同名的变量或函数基类的同名成员将被隐藏这种现象称为隐藏Hiding。也叫重定义同名成员在派生类中会覆盖基类中的成员导致基类成员无法被直接访问。 示例代码 class Person { protected:int _num 111; // 身份证号 };class Student : public Person { public:Student(int num) : _num(num) {} // 派生类中的_num覆盖了基类中的_numvoid Print() {cout 身份证号: Person::_num endl; // 访问基类中的_numcout 学号: _num endl; // 访问派生类中的_num}protected:int _num; // 学号 };int main() {Student s(999);s.Print(); // 输出身份证号和学号return 0; }在这个例子中Student 类中定义了一个 _num 变量它隐藏了基类 Person 中的同名变量。为了访问基类的 _num我们使用了 Person::_num 来显式地指定访问基类中的成员。这样可以避免由于成员同名而导致的混淆。 注意在实际中在继承体系里面最好不要定义同名的成员。 3.1.1 函数的隐藏 同名成员函数也会构成隐藏只要函数名称相同即使参数列表不同也会发生隐藏。这种行为和函数重载不同。在派生类中如果我们希望访问基类中的同名函数必须显式调用基类的函数。 class A { public:void fun() {cout A::fun() endl;} };class B : public A { public:void fun(int i) { // 隐藏了基类的fun()cout B::fun(int i) - i endl;} };int main() {B b;b.fun(10); // 调用B::fun(int i)b.A::fun(); // 显式调用基类的fun()return 0; }在此代码中派生类 B 中的 fun(int i) 函数隐藏了基类 A 中的 fun() 函数。如果我们希望调用基类的 fun() 函数必须通过 b.A::fun() 来显式调用。这与函数重载不同函数隐藏仅要求函数名相同而不考虑参数列表。并且函数重载说的是同一作用域而这里基类和派生类时两个作用域 3.2 派生类的默认成员函数 在 C 中当我们不显式定义类的构造函数、拷贝构造函数、赋值运算符和析构函数时编译器会自动为我们生成这些函数。这些自动生成的函数在派生类中也会涉及到对基类成员的操作因此在继承体系中了解这些默认成员函数的调用规则非常重要。 3.2.1 构造函数的调用顺序 在派生类对象的构造过程中基类的构造函数会优先于派生类的构造函数被调用。如果基类没有默认构造函数则派生类的构造函数必须在初始化列表中显式调用基类的构造函数。 class Person { public:Person(const string name) : _name(name) {cout Person constructor called! endl;}protected:string _name; };class Student : public Person { public:Student(const string name, int stuid) : Person(name), _stuid(stuid) {cout Student constructor called! endl;}private:int _stuid; };int main() {Student s(Alice, 12345);return 0; }输出 Person constructor called! Student constructor called!在这个例子中Student 类的构造函数首先调用了 Person 类的构造函数来初始化基类部分。随后才执行派生类 Student 的构造函数。这种调用顺序确保基类的成员在派生类构造之前就已经被正确初始化。 3.2.2 拷贝构造函数与赋值运算符的调用 当派生类对象被拷贝时基类的拷贝构造函数会先被调用然后才是派生类的拷贝构造函数。同样赋值运算符的调用顺序也遵循这一规则基类的赋值运算符会先于派生类的赋值运算符被调用。 class Person { public:Person(const string name) : _name(name) {}// 拷贝构造函数Person(const Person p) {_name p._name;cout Person copy constructor called! endl;}// 赋值运算符Person operator(const Person p) {_name p._name;cout Person assignment operator called! endl;return *this;}protected:string _name; };class Student : public Person { public:Student(const string name, int stuid) : Person(name), _stuid(stuid) {}// 拷贝构造函数Student(const Student s) : Person(s) {_stuid s._stuid;cout Student copy constructor called! endl;}// 赋值运算符Student operator(const Student s) {Person::operator(s); // 先调用基类的赋值运算符_stuid s._stuid;cout Student assignment operator called! endl;return *this;}private:int _stuid; };int main() {Student s1(Alice, 12345);Student s2 s1; // 拷贝构造函数Student s3(Bob, 54321);s3 s1; // 赋值运算符return 0; }输出 Person copy constructor called! Student copy constructor called! Person assignment operator called! Student assignment operator called!在拷贝构造和赋值操作过程中基类部分总是优先于派生类部分进行初始化或赋值操作。为了保证派生类对象的完整性派生类的拷贝构造函数和赋值运算符必须调用基类的相应函数确保基类成员正确处理。 3.2.3 析构函数的调用顺序 与构造函数的调用顺序相反析构函数的调用顺序是先调用派生类的析构函数然后再调用基类的析构函数。这确保了派生类的资源先被释放然后基类的资源才能安全地释放。 class Person { public:Person(const string name) : _name(name) {}~Person() {cout Person destructor called! endl;}protected:string _name; };class Student : public Person { public:Student(const string name, int stuid) : Person(name), _stuid(stuid) {}~Student() {cout Student destructor called! endl;}private:int _stuid; };int main() {Student s(Alice, 12345);return 0; }输出 Student destructor called! Person destructor called!可以看到当 Student 对象 s 析构时首先调用了 Student 的析构函数随后调用了 Person 的析构函数。这种析构顺序确保派生类资源如成员变量 _stuid被先行清理而基类的资源如 _name则在派生类资源清理后再进行释放。 3.2.4 虚析构函数 在继承体系中若希望基类指针指向派生类对象并通过该指针安全地释放对象基类的析构函数应当定义为虚函数。否则仅会调用基类的析构函数导致派生类资源没有正确释放从而引发内存泄漏。 class Person { public:Person(const string name) : _name(name) {}virtual ~Person() {cout Person destructor called! endl;}protected:string _name; };class Student : public Person { public:Student(const string name, int stuid) : Person(name), _stuid(stuid) {}~Student() {cout Student destructor called! endl;}private:int _stuid; };int main() {Person* p new Student(Alice, 12345);delete p; // 安全删除先调用派生类的析构函数return 0; }输出 Student destructor called! Person destructor called!通过将基类的析构函数声明为 virtual当通过基类指针删除派生类对象时派生类的析构函数将首先被调用从而确保所有派生类的资源被正确释放。 总结 通过本篇文章的学习我们深入了解了 C 中继承的基本概念、继承方式对成员访问的影响、对象赋值转换的机制以及如何处理同名成员的隐藏问题。我们还讨论了派生类默认成员函数的调用顺序和析构函数的正确使用方式。 继承机制使得我们能够有效地复用代码同时为程序设计提供了层次结构。但在实际开发中继承的设计需要谨慎避免出现复杂的层次结构。在下一篇文章中我们将进一步探讨 虚拟继承 的使用解决多继承中常见的问题敬请期待 讨论区如果你在学习过程中有任何疑问欢迎在评论区留言讨论。 支持一下如果你觉得这篇文章对你有帮助请点赞、收藏并分享给更多 C 学习者你的支持是我继续创作的动力。 以上就是关于【C篇】继承之韵解构编程奥义领略面向对象的至高法则的内容啦各位大佬有什么问题欢迎在评论区指正或者私信我也是可以的啦您的支持是我创作的最大动力❤️
http://www.w-s-a.com/news/55420/

相关文章:

  • 什么颜色做网站显的大气网站建设的含盖哪方面
  • 没网站怎么做二维码扫描连接济南做网站推广哪家好
  • 台州建设规划局网站搞外贸一般是干什么的
  • 怎么提高自己网站的知名度电子商务是建网站
  • 官方查企业的网站办公用品网站建设策划书
  • 微信网站搭建哪家好网站中转页
  • 阿里巴巴网站开发是谁长沙自助模板建站
  • 阿里云网站方案建设书网络公司运营是干啥的
  • 南通seo网站排名优化nginx wordpress rewrite
  • 网站做成软件做内部网站费用
  • 浙江企业网站建设网站域名有了 网站如何建设
  • 学编程哪个机构有权威德州做网站优化
  • 最火的网站开发语言福州网站建设服务商
  • 嘉兴网站制作哪里好asp网站源码免费版
  • 如何给网站配置域名百度网站统计添加网址
  • 搭建wap网站磁力引擎
  • 如何给公司网站做推广个人网站可以做社区吗
  • 网站建设为什么不给源代码大理如何做百度的网站
  • 网站代理违法吗网站备份流程
  • 免费域名查询网站wordpress wordfence
  • h5响应式网站模板制作巴南网站制作
  • 网站方案报价软文什么意思
  • 电子商城网站如何建设上海公司车牌价格
  • 丽江网站设计公司专业公司网站设计企业
  • iis怎么建设网站特色产品推广方案
  • 道路建设网站专题品牌网站建设特色大蝌蚪
  • 网站开发组合 所有组合如何做com的网站
  • 电商网站怎么做的Wordpress 报表的插件
  • 纹理网站推荐买了两台服务器可以做网站吗
  • 机关公文写作网站南宁互联网推广